diff options
Diffstat (limited to 'src/test/regress/sql/tidscan.sql')
-rw-r--r-- | src/test/regress/sql/tidscan.sql | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/test/regress/sql/tidscan.sql b/src/test/regress/sql/tidscan.sql new file mode 100644 index 0000000..313e0fb --- /dev/null +++ b/src/test/regress/sql/tidscan.sql @@ -0,0 +1,104 @@ +-- tests for tidscans + +CREATE TABLE tidscan(id integer); + +-- only insert a few rows, we don't want to spill onto a second table page +INSERT INTO tidscan VALUES (1), (2), (3); + +-- show ctids +SELECT ctid, * FROM tidscan; + +-- ctid equality - implemented as tidscan +EXPLAIN (COSTS OFF) +SELECT ctid, * FROM tidscan WHERE ctid = '(0,1)'; +SELECT ctid, * FROM tidscan WHERE ctid = '(0,1)'; + +EXPLAIN (COSTS OFF) +SELECT ctid, * FROM tidscan WHERE '(0,1)' = ctid; +SELECT ctid, * FROM tidscan WHERE '(0,1)' = ctid; + +-- OR'd clauses +EXPLAIN (COSTS OFF) +SELECT ctid, * FROM tidscan WHERE ctid = '(0,2)' OR '(0,1)' = ctid; +SELECT ctid, * FROM tidscan WHERE ctid = '(0,2)' OR '(0,1)' = ctid; + +-- ctid = ScalarArrayOp - implemented as tidscan +EXPLAIN (COSTS OFF) +SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]); +SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]); + +-- ctid != ScalarArrayOp - can't be implemented as tidscan +EXPLAIN (COSTS OFF) +SELECT ctid, * FROM tidscan WHERE ctid != ANY(ARRAY['(0,1)', '(0,2)']::tid[]); +SELECT ctid, * FROM tidscan WHERE ctid != ANY(ARRAY['(0,1)', '(0,2)']::tid[]); + +-- tid equality extracted from sub-AND clauses +EXPLAIN (COSTS OFF) +SELECT ctid, * FROM tidscan +WHERE (id = 3 AND ctid IN ('(0,2)', '(0,3)')) OR (ctid = '(0,1)' AND id = 1); +SELECT ctid, * FROM tidscan +WHERE (id = 3 AND ctid IN ('(0,2)', '(0,3)')) OR (ctid = '(0,1)' AND id = 1); + +-- nestloop-with-inner-tidscan joins on tid +SET enable_hashjoin TO off; -- otherwise hash join might win +EXPLAIN (COSTS OFF) +SELECT t1.ctid, t1.*, t2.ctid, t2.* +FROM tidscan t1 JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; +SELECT t1.ctid, t1.*, t2.ctid, t2.* +FROM tidscan t1 JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; +EXPLAIN (COSTS OFF) +SELECT t1.ctid, t1.*, t2.ctid, t2.* +FROM tidscan t1 LEFT JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; +SELECT t1.ctid, t1.*, t2.ctid, t2.* +FROM tidscan t1 LEFT JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1; +RESET enable_hashjoin; + +-- exercise backward scan and rewind +BEGIN; +DECLARE c CURSOR FOR +SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]); +FETCH ALL FROM c; +FETCH BACKWARD 1 FROM c; +FETCH FIRST FROM c; +ROLLBACK; + +-- tidscan via CURRENT OF +BEGIN; +DECLARE c CURSOR FOR SELECT ctid, * FROM tidscan; +FETCH NEXT FROM c; -- skip one row +FETCH NEXT FROM c; +-- perform update +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; +FETCH NEXT FROM c; +-- perform update +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; +SELECT * FROM tidscan; +-- position cursor past any rows +FETCH NEXT FROM c; +-- should error out +EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) +UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; +ROLLBACK; + +-- bulk joins on CTID +-- (these plans don't use TID scans, but this still seems like an +-- appropriate place for these tests) +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid; +SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid; +SET enable_hashjoin TO off; +EXPLAIN (COSTS OFF) +SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid; +SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid; +RESET enable_hashjoin; + +-- check predicate lock on CTID +BEGIN ISOLATION LEVEL SERIALIZABLE; +SELECT * FROM tidscan WHERE ctid = '(0,1)'; +-- locktype should be 'tuple' +SELECT locktype, mode FROM pg_locks WHERE pid = pg_backend_pid() AND mode = 'SIReadLock'; +ROLLBACK; + +DROP TABLE tidscan; |