Add support for AT LOCAL
[pgsql.git] / src / test / regress / expected / tidscan.out
blobf133b5a4ac70fba94be51f32a541fb3c05ee0872
1 -- tests for tidscans
2 CREATE TABLE tidscan(id integer);
3 -- only insert a few rows, we don't want to spill onto a second table page
4 INSERT INTO tidscan VALUES (1), (2), (3);
5 -- show ctids
6 SELECT ctid, * FROM tidscan;
7  ctid  | id 
8 -------+----
9  (0,1) |  1
10  (0,2) |  2
11  (0,3) |  3
12 (3 rows)
14 -- ctid equality - implemented as tidscan
15 EXPLAIN (COSTS OFF)
16 SELECT ctid, * FROM tidscan WHERE ctid = '(0,1)';
17             QUERY PLAN             
18 -----------------------------------
19  Tid Scan on tidscan
20    TID Cond: (ctid = '(0,1)'::tid)
21 (2 rows)
23 SELECT ctid, * FROM tidscan WHERE ctid = '(0,1)';
24  ctid  | id 
25 -------+----
26  (0,1) |  1
27 (1 row)
29 EXPLAIN (COSTS OFF)
30 SELECT ctid, * FROM tidscan WHERE '(0,1)' = ctid;
31             QUERY PLAN             
32 -----------------------------------
33  Tid Scan on tidscan
34    TID Cond: ('(0,1)'::tid = ctid)
35 (2 rows)
37 SELECT ctid, * FROM tidscan WHERE '(0,1)' = ctid;
38  ctid  | id 
39 -------+----
40  (0,1) |  1
41 (1 row)
43 -- OR'd clauses
44 EXPLAIN (COSTS OFF)
45 SELECT ctid, * FROM tidscan WHERE ctid = '(0,2)' OR '(0,1)' = ctid;
46                           QUERY PLAN                          
47 --------------------------------------------------------------
48  Tid Scan on tidscan
49    TID Cond: ((ctid = '(0,2)'::tid) OR ('(0,1)'::tid = ctid))
50 (2 rows)
52 SELECT ctid, * FROM tidscan WHERE ctid = '(0,2)' OR '(0,1)' = ctid;
53  ctid  | id 
54 -------+----
55  (0,1) |  1
56  (0,2) |  2
57 (2 rows)
59 -- ctid = ScalarArrayOp - implemented as tidscan
60 EXPLAIN (COSTS OFF)
61 SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]);
62                       QUERY PLAN                       
63 -------------------------------------------------------
64  Tid Scan on tidscan
65    TID Cond: (ctid = ANY ('{"(0,1)","(0,2)"}'::tid[]))
66 (2 rows)
68 SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]);
69  ctid  | id 
70 -------+----
71  (0,1) |  1
72  (0,2) |  2
73 (2 rows)
75 -- ctid != ScalarArrayOp - can't be implemented as tidscan
76 EXPLAIN (COSTS OFF)
77 SELECT ctid, * FROM tidscan WHERE ctid != ANY(ARRAY['(0,1)', '(0,2)']::tid[]);
78                       QUERY PLAN                      
79 ------------------------------------------------------
80  Seq Scan on tidscan
81    Filter: (ctid <> ANY ('{"(0,1)","(0,2)"}'::tid[]))
82 (2 rows)
84 SELECT ctid, * FROM tidscan WHERE ctid != ANY(ARRAY['(0,1)', '(0,2)']::tid[]);
85  ctid  | id 
86 -------+----
87  (0,1) |  1
88  (0,2) |  2
89  (0,3) |  3
90 (3 rows)
92 -- tid equality extracted from sub-AND clauses
93 EXPLAIN (COSTS OFF)
94 SELECT ctid, * FROM tidscan
95 WHERE (id = 3 AND ctid IN ('(0,2)', '(0,3)')) OR (ctid = '(0,1)' AND id = 1);
96                                                   QUERY PLAN                                                  
97 --------------------------------------------------------------------------------------------------------------
98  Tid Scan on tidscan
99    TID Cond: ((ctid = ANY ('{"(0,2)","(0,3)"}'::tid[])) OR (ctid = '(0,1)'::tid))
100    Filter: (((id = 3) AND (ctid = ANY ('{"(0,2)","(0,3)"}'::tid[]))) OR ((ctid = '(0,1)'::tid) AND (id = 1)))
101 (3 rows)
103 SELECT ctid, * FROM tidscan
104 WHERE (id = 3 AND ctid IN ('(0,2)', '(0,3)')) OR (ctid = '(0,1)' AND id = 1);
105  ctid  | id 
106 -------+----
107  (0,1) |  1
108  (0,3) |  3
109 (2 rows)
111 -- nestloop-with-inner-tidscan joins on tid
112 SET enable_hashjoin TO off;  -- otherwise hash join might win
113 EXPLAIN (COSTS OFF)
114 SELECT t1.ctid, t1.*, t2.ctid, t2.*
115 FROM tidscan t1 JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1;
116              QUERY PLAN             
117 ------------------------------------
118  Nested Loop
119    ->  Seq Scan on tidscan t1
120          Filter: (id = 1)
121    ->  Tid Scan on tidscan t2
122          TID Cond: (t1.ctid = ctid)
123 (5 rows)
125 SELECT t1.ctid, t1.*, t2.ctid, t2.*
126 FROM tidscan t1 JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1;
127  ctid  | id | ctid  | id 
128 -------+----+-------+----
129  (0,1) |  1 | (0,1) |  1
130 (1 row)
132 EXPLAIN (COSTS OFF)
133 SELECT t1.ctid, t1.*, t2.ctid, t2.*
134 FROM tidscan t1 LEFT JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1;
135              QUERY PLAN             
136 ------------------------------------
137  Nested Loop Left Join
138    ->  Seq Scan on tidscan t1
139          Filter: (id = 1)
140    ->  Tid Scan on tidscan t2
141          TID Cond: (t1.ctid = ctid)
142 (5 rows)
144 SELECT t1.ctid, t1.*, t2.ctid, t2.*
145 FROM tidscan t1 LEFT JOIN tidscan t2 ON t1.ctid = t2.ctid WHERE t1.id = 1;
146  ctid  | id | ctid  | id 
147 -------+----+-------+----
148  (0,1) |  1 | (0,1) |  1
149 (1 row)
151 RESET enable_hashjoin;
152 -- exercise backward scan and rewind
153 BEGIN;
154 DECLARE c CURSOR FOR
155 SELECT ctid, * FROM tidscan WHERE ctid = ANY(ARRAY['(0,1)', '(0,2)']::tid[]);
156 FETCH ALL FROM c;
157  ctid  | id 
158 -------+----
159  (0,1) |  1
160  (0,2) |  2
161 (2 rows)
163 FETCH BACKWARD 1 FROM c;
164  ctid  | id 
165 -------+----
166  (0,2) |  2
167 (1 row)
169 FETCH FIRST FROM c;
170  ctid  | id 
171 -------+----
172  (0,1) |  1
173 (1 row)
175 ROLLBACK;
176 -- tidscan via CURRENT OF
177 BEGIN;
178 DECLARE c CURSOR FOR SELECT ctid, * FROM tidscan;
179 FETCH NEXT FROM c; -- skip one row
180  ctid  | id 
181 -------+----
182  (0,1) |  1
183 (1 row)
185 FETCH NEXT FROM c;
186  ctid  | id 
187 -------+----
188  (0,2) |  2
189 (1 row)
191 -- perform update
192 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
193 UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *;
194                     QUERY PLAN                     
195 ---------------------------------------------------
196  Update on tidscan (actual rows=1 loops=1)
197    ->  Tid Scan on tidscan (actual rows=1 loops=1)
198          TID Cond: CURRENT OF c
199 (3 rows)
201 FETCH NEXT FROM c;
202  ctid  | id 
203 -------+----
204  (0,3) |  3
205 (1 row)
207 -- perform update
208 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
209 UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *;
210                     QUERY PLAN                     
211 ---------------------------------------------------
212  Update on tidscan (actual rows=1 loops=1)
213    ->  Tid Scan on tidscan (actual rows=1 loops=1)
214          TID Cond: CURRENT OF c
215 (3 rows)
217 SELECT * FROM tidscan;
218  id 
219 ----
220   1
221  -2
222  -3
223 (3 rows)
225 -- position cursor past any rows
226 FETCH NEXT FROM c;
227  ctid | id 
228 ------+----
229 (0 rows)
231 -- should error out
232 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
233 UPDATE tidscan SET id = -id WHERE CURRENT OF c RETURNING *;
234 ERROR:  cursor "c" is not positioned on a row
235 ROLLBACK;
236 -- bulk joins on CTID
237 -- (these plans don't use TID scans, but this still seems like an
238 -- appropriate place for these tests)
239 EXPLAIN (COSTS OFF)
240 SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid;
241                QUERY PLAN               
242 ----------------------------------------
243  Aggregate
244    ->  Hash Join
245          Hash Cond: (t1.ctid = t2.ctid)
246          ->  Seq Scan on tenk1 t1
247          ->  Hash
248                ->  Seq Scan on tenk1 t2
249 (6 rows)
251 SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid;
252  count 
253 -------
254  10000
255 (1 row)
257 SET enable_hashjoin TO off;
258 EXPLAIN (COSTS OFF)
259 SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid;
260                QUERY PLAN                
261 -----------------------------------------
262  Aggregate
263    ->  Merge Join
264          Merge Cond: (t1.ctid = t2.ctid)
265          ->  Sort
266                Sort Key: t1.ctid
267                ->  Seq Scan on tenk1 t1
268          ->  Sort
269                Sort Key: t2.ctid
270                ->  Seq Scan on tenk1 t2
271 (9 rows)
273 SELECT count(*) FROM tenk1 t1 JOIN tenk1 t2 ON t1.ctid = t2.ctid;
274  count 
275 -------
276  10000
277 (1 row)
279 RESET enable_hashjoin;
280 -- check predicate lock on CTID
281 BEGIN ISOLATION LEVEL SERIALIZABLE;
282 SELECT * FROM tidscan WHERE ctid = '(0,1)';
283  id 
284 ----
285   1
286 (1 row)
288 -- locktype should be 'tuple'
289 SELECT locktype, mode FROM pg_locks WHERE pid = pg_backend_pid() AND mode = 'SIReadLock';
290  locktype |    mode    
291 ----------+------------
292  tuple    | SIReadLock
293 (1 row)
295 ROLLBACK;
296 DROP TABLE tidscan;