mirror of https://github.com/postgres/postgres
TidScan plan nodes were not systematically tested before. These additions raise the LOC coverage number for the basic regression tests from 52% to 92% in nodeTidscan.c, and from 60% to 93% in tidpath.c. Andres Freund, tweaked a bit by me Discussion: https://postgr.es/m/20170320062511.hp5qeurtxrwsvfxr@alap3.anarazel.depull/17/merge
parent
9cf6033281
commit
be6c3d19fd
@ -0,0 +1,179 @@ |
|||||||
|
-- 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 | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(0,2) | 2 |
||||||
|
(0,3) | 3 |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
-- ctid equality - implemented as tidscan |
||||||
|
EXPLAIN (COSTS OFF) |
||||||
|
SELECT ctid, * FROM tidscan WHERE ctid = '(0,1)'; |
||||||
|
QUERY PLAN |
||||||
|
----------------------------------- |
||||||
|
Tid Scan on tidscan |
||||||
|
TID Cond: (ctid = '(0,1)'::tid) |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
SELECT ctid, * FROM tidscan WHERE ctid = '(0,1)'; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
EXPLAIN (COSTS OFF) |
||||||
|
SELECT ctid, * FROM tidscan WHERE '(0,1)' = ctid; |
||||||
|
QUERY PLAN |
||||||
|
----------------------------------- |
||||||
|
Tid Scan on tidscan |
||||||
|
TID Cond: ('(0,1)'::tid = ctid) |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
SELECT ctid, * FROM tidscan WHERE '(0,1)' = ctid; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
-- ctid = ScalarArrayOp - implemented as tidscan |
||||||
|
EXPLAIN (COSTS OFF) |
||||||
|
SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]); |
||||||
|
QUERY PLAN |
||||||
|
------------------------------------------------------- |
||||||
|
Tid Scan on tidscan |
||||||
|
TID Cond: (ctid = ANY ('{"(0,1)","(0,2)"}'::tid[])) |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]); |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(0,2) | 2 |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
-- ctid != ScalarArrayOp - can't be implemented as tidscan |
||||||
|
EXPLAIN (COSTS OFF) |
||||||
|
SELECT ctid, * FROM tidscan WHERE ctid != ANY(ARRAY['(0,1)', '(0,2)']::tid[]); |
||||||
|
QUERY PLAN |
||||||
|
------------------------------------------------------ |
||||||
|
Seq Scan on tidscan |
||||||
|
Filter: (ctid <> ANY ('{"(0,1)","(0,2)"}'::tid[])) |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
SELECT ctid, * FROM tidscan WHERE ctid != ANY(ARRAY['(0,1)', '(0,2)']::tid[]); |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(0,2) | 2 |
||||||
|
(0,3) | 3 |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
-- 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); |
||||||
|
QUERY PLAN |
||||||
|
-------------------------------------------------------------------------------------------------------------- |
||||||
|
Tid Scan on tidscan |
||||||
|
TID Cond: ((ctid = ANY ('{"(0,2)","(0,3)"}'::tid[])) OR (ctid = '(0,1)'::tid)) |
||||||
|
Filter: (((id = 3) AND (ctid = ANY ('{"(0,2)","(0,3)"}'::tid[]))) OR ((ctid = '(0,1)'::tid) AND (id = 1))) |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
SELECT ctid, * FROM tidscan |
||||||
|
WHERE (id = 3 AND ctid IN ('(0,2)', '(0,3)')) OR (ctid = '(0,1)' AND id = 1); |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(0,3) | 3 |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
-- 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; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(0,2) | 2 |
||||||
|
(2 rows) |
||||||
|
|
||||||
|
FETCH BACKWARD 1 FROM c; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,2) | 2 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
FETCH FIRST FROM c; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
ROLLBACK; |
||||||
|
-- tidscan via CURRENT OF |
||||||
|
BEGIN; |
||||||
|
DECLARE c CURSOR FOR SELECT ctid, * FROM tidscan; |
||||||
|
FETCH NEXT FROM c; -- skip one row |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,1) | 1 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
FETCH NEXT FROM c; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,2) | 2 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
-- perform update |
||||||
|
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) |
||||||
|
UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; |
||||||
|
QUERY PLAN |
||||||
|
--------------------------------------------------- |
||||||
|
Update on tidscan (actual rows=1 loops=1) |
||||||
|
-> Tid Scan on tidscan (actual rows=1 loops=1) |
||||||
|
TID Cond: CURRENT OF c |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
FETCH NEXT FROM c; |
||||||
|
ctid | id |
||||||
|
-------+---- |
||||||
|
(0,3) | 3 |
||||||
|
(1 row) |
||||||
|
|
||||||
|
-- perform update |
||||||
|
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) |
||||||
|
UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; |
||||||
|
QUERY PLAN |
||||||
|
--------------------------------------------------- |
||||||
|
Update on tidscan (actual rows=1 loops=1) |
||||||
|
-> Tid Scan on tidscan (actual rows=1 loops=1) |
||||||
|
TID Cond: CURRENT OF c |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
SELECT * FROM tidscan; |
||||||
|
id |
||||||
|
---- |
||||||
|
1 |
||||||
|
-2 |
||||||
|
-3 |
||||||
|
(3 rows) |
||||||
|
|
||||||
|
-- position cursor past any rows |
||||||
|
FETCH NEXT FROM c; |
||||||
|
ctid | id |
||||||
|
------+---- |
||||||
|
(0 rows) |
||||||
|
|
||||||
|
-- should error out |
||||||
|
EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) |
||||||
|
UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *; |
||||||
|
ERROR: cursor "c" is not positioned on a row |
||||||
|
ROLLBACK; |
||||||
|
DROP TABLE tidscan; |
@ -0,0 +1,66 @@ |
|||||||
|
-- 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; |
||||||
|
|
||||||
|
-- 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); |
||||||
|
|
||||||
|
-- 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; |
||||||
|
|
||||||
|
DROP TABLE tidscan; |
Loading…
Reference in new issue