#
# Session 3 starts with a cursor on table and fetches one row.
# Then it opens another cursor and closes the old one.
#
# This advances MyProc->xmin without resetting TransactionXmin.
#
# Then when fetching from the 3nd cursor, it hits a row
# with xmin that is a subxid. The subxid is greater than
# snapshot xmin, so it calls SubTransGetTopmostTransaction() on it
# Its parent is newer than TransactionXmin but older than
# Myproc->xmin. The pg_subtrans that has been truncated already,
# SubTransGetTopmostTransaction() fails to find it, and you get
# ERROR:  could not access status of transaction 16280360
#
#
# Sessions 1 and 2 set up the rows with right XIDs for session 3 to
# scan and hit that problem
#

setup
{
DROP TABLE IF EXISTS atbl, btbl;
CREATE TABLE mytbl (subx integer, val integer) WITH (autovacuum_enabled=false);
INSERT INTO mytbl SELECT g, g FROM generate_series(1, 1000) g;

CREATE OR REPLACE FUNCTION gen_subxids (n integer, m integer)
 RETURNS VOID
 LANGUAGE plpgsql
AS $$
BEGIN
  for i in 0..m loop
    perform gen_subxids(n);
  end loop;
END;
$$;

CREATE OR REPLACE FUNCTION gen_subxids (n integer)
 RETURNS VOID
 LANGUAGE plpgsql
AS $$
BEGIN
  IF n <= 0 THEN
    EXECUTE 'INSERT INTO mytbl VALUES (1, 2)';
  ELSE
    PERFORM gen_subxids(n - 1);
  END IF;
EXCEPTION /* generates a subxid */
  WHEN raise_exception THEN NULL;
END;
$$;
}

teardown
{
 DROP TABLE mytbl;
 DROP FUNCTION gen_subxids(integer);
 DROP FUNCTION gen_subxids(integer, integer);
}

session s1
step s1begin	{ BEGIN; }
step s1gen	{ SELECT gen_subxids(100, 1000); }
step s1c	{ COMMIT; }

step checkpoint	{ CHECKPOINT; }

session s2
step s2begin	{ BEGIN; select txid_current(); }
step s2gen	{ SELECT gen_subxids(100, 1000); }
step s2c	{ COMMIT; }

# Session 3
session s3
step s3begin	{ BEGIN ISOLATION LEVEL READ COMMITTED; }
step s3read	{ SELECT count(*) FROM mytbl; }

step s3adeclare	{ DECLARE acur CURSOR FOR SELECT * FROM mytbl; }
step s3afetchone { FETCH FROM acur; }
step s3afetchall { FETCH ALL FROM acur; }
step s3aclose	{ CLOSE acur; }

step s3bdeclare	{ DECLARE bcur CURSOR FOR SELECT * FROM mytbl; }
step s3bfetchone { FETCH FROM bcur; }
step s3bfetchall { FETCH ALL FROM bcur; }

step s3c	{ COMMIT; }

permutation s3begin s3adeclare s3afetchone s1begin s1gen s2begin s1gen s2gen s1c checkpoint s3bdeclare s3bfetchone s3aclose checkpoint  s3bfetchall s3c s2c
