text: -- tests for tidrangescans
  
  SET enable_seqscan TO off;
  CREATE TABLE tidrangescan(id integer, data text);
  
  -- empty table
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid < '(1, 0)';
  SELECT ctid FROM tidrangescan WHERE ctid < '(1, 0)';
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid > '(9, 0)';
  SELECT ctid FROM tidrangescan WHERE ctid > '(9, 0)';
  
  -- insert enough tuples to fill at least two pages
  INSERT INTO tidrangescan SELECT i,repeat('x', 100) FROM generate_series(1,200) AS s(i);
  
  -- remove all tuples after the 10th tuple on each page.  Trying to ensure
  -- we get the same layout with all CPU architectures and smaller than standard
  -- page sizes.
  DELETE FROM tidrangescan
  WHERE substring(ctid::text FROM ',(\d+)\)')::integer > 10 OR substring(ctid::text FROM '\((\d+),')::integer > 2;
  VACUUM tidrangescan;
  
  -- range scans with upper bound
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid < '(1,0)';
  SELECT ctid FROM tidrangescan WHERE ctid < '(1,0)';
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid <= '(1,5)';
  SELECT ctid FROM tidrangescan WHERE ctid <= '(1,5)';
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid < '(0,0)';
  SELECT ctid FROM tidrangescan WHERE ctid < '(0,0)';
  
  -- range scans with lower bound
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid > '(2,8)';
  SELECT ctid FROM tidrangescan WHERE ctid > '(2,8)';
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE '(2,8)' < ctid;
  SELECT ctid FROM tidrangescan WHERE '(2,8)' < ctid;
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid >= '(2,8)';
  SELECT ctid FROM tidrangescan WHERE ctid >= '(2,8)';
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid >= '(100,0)';
  SELECT ctid FROM tidrangescan WHERE ctid >= '(100,0)';
  
  -- range scans with both bounds
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE ctid > '(1,4)' AND '(1,7)' >= ctid;
  SELECT ctid FROM tidrangescan WHERE ctid > '(1,4)' AND '(1,7)' >= ctid;
  
  EXPLAIN (COSTS OFF)
  SELECT ctid FROM tidrangescan WHERE '(1,7)' >= ctid AND ctid > '(1,4)';
  SELECT ctid FROM tidrangescan WHERE '(1,7)' >= ctid AND ctid > '(1,4)';
  
  -- extreme offsets
  SELECT ctid FROM tidrangescan WHERE ctid > '(0,65535)' AND ctid < '(1,0)' LIMIT 1;
  SELECT ctid FROM tidrangescan WHERE ctid < '(0,0)' LIMIT 1;
  
  SELECT ctid FROM tidrangescan WHERE ctid > '(4294967295,65535)';
  SELECT ctid FROM tidrangescan WHERE ctid < '(0,0)';
  
  -- NULLs in the range cannot return tuples
  SELECT ctid FROM tidrangescan WHERE ctid >= (SELECT NULL::tid);
  
  -- rescans
  EXPLAIN (COSTS OFF)
  SELECT t.ctid,t2.c FROM tidrangescan t,
  LATERAL (SELECT count(*) c FROM tidrangescan t2 WHERE t2.ctid <= t.ctid) t2
  WHERE t.ctid < '(1,0)';
  
  SELECT t.ctid,t2.c FROM tidrangescan t,
  LATERAL (SELECT count(*) c FROM tidrangescan t2 WHERE t2.ctid <= t.ctid) t2
  WHERE t.ctid < '(1,0)';
  
  -- cursors
  
  -- Ensure we get a TID Range scan without a Materialize node.
  EXPLAIN (COSTS OFF)
  DECLARE c SCROLL CURSOR FOR SELECT ctid FROM tidrangescan WHERE ctid < '(1,0)';
  
  BEGIN;
  DECLARE c SCROLL CURSOR FOR SELECT ctid FROM tidrangescan WHERE ctid < '(1,0)';
  FETCH NEXT c;
  FETCH NEXT c;
  FETCH PRIOR c;
  FETCH FIRST c;
  FETCH LAST c;
  COMMIT;
  
  DROP TABLE tidrangescan;
  
  RESET enable_seqscan;
  