2 -- Cursor regression tests
7 DECLARE foo1 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
9 DECLARE foo2 SCROLL CURSOR FOR SELECT * FROM tenk2;
11 DECLARE foo3 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
13 DECLARE foo4 SCROLL CURSOR FOR SELECT * FROM tenk2;
15 DECLARE foo5 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
17 DECLARE foo6 SCROLL CURSOR FOR SELECT * FROM tenk2;
19 DECLARE foo7 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
21 DECLARE foo8 SCROLL CURSOR FOR SELECT * FROM tenk2;
23 DECLARE foo9 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
25 DECLARE foo10 SCROLL CURSOR FOR SELECT * FROM tenk2;
27 DECLARE foo11 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
29 DECLARE foo12 SCROLL CURSOR FOR SELECT * FROM tenk2;
31 DECLARE foo13 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
33 DECLARE foo14 SCROLL CURSOR FOR SELECT * FROM tenk2;
35 DECLARE foo15 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
37 DECLARE foo16 SCROLL CURSOR FOR SELECT * FROM tenk2;
39 DECLARE foo17 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
41 DECLARE foo18 SCROLL CURSOR FOR SELECT * FROM tenk2;
43 DECLARE foo19 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
45 DECLARE foo20 SCROLL CURSOR FOR SELECT * FROM tenk2;
47 DECLARE foo21 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
49 DECLARE foo22 SCROLL CURSOR FOR SELECT * FROM tenk2;
51 DECLARE foo23 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
99 FETCH backward 1 in foo23;
101 FETCH backward 2 in foo22;
103 FETCH backward 3 in foo21;
105 FETCH backward 4 in foo20;
107 FETCH backward 5 in foo19;
109 FETCH backward 6 in foo18;
111 FETCH backward 7 in foo17;
113 FETCH backward 8 in foo16;
115 FETCH backward 9 in foo15;
117 FETCH backward 10 in foo14;
119 FETCH backward 11 in foo13;
121 FETCH backward 12 in foo12;
123 FETCH backward 13 in foo11;
125 FETCH backward 14 in foo10;
127 FETCH backward 15 in foo9;
129 FETCH backward 16 in foo8;
131 FETCH backward 17 in foo7;
133 FETCH backward 18 in foo6;
135 FETCH backward 19 in foo5;
137 FETCH backward 20 in foo4;
139 FETCH backward 21 in foo3;
141 FETCH backward 22 in foo2;
143 FETCH backward 23 in foo1;
169 -- leave some cursors open, to test that auto-close works.
171 -- record this in the system view as well (don't query the time field there
173 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors ORDER BY 1;
177 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors;
180 -- NO SCROLL disallows backward fetching
185 DECLARE foo24 NO SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2;
189 FETCH BACKWARD 1 FROM foo24; -- should fail
194 -- Cursors outside transaction blocks
198 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors;
202 DECLARE foo25 SCROLL CURSOR WITH HOLD FOR SELECT * FROM tenk2;
212 FETCH BACKWARD FROM foo25;
214 FETCH ABSOLUTE -1 FROM foo25;
216 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors;
221 -- ROLLBACK should close holdable cursors
226 DECLARE foo26 CURSOR WITH HOLD FOR SELECT * FROM tenk1 ORDER BY unique2;
234 -- Parameterized DECLARE needs to insert param values into the cursor portal
239 CREATE FUNCTION declares_cursor(text)
241 AS 'DECLARE c CURSOR FOR SELECT stringu1 FROM tenk1 WHERE stringu1 LIKE $1;'
244 SELECT declares_cursor('AB%');
251 -- Test behavior of both volatile and stable functions inside a cursor;
252 -- in particular we want to see what happens during commit of a holdable
256 create temp table tt1(f1 int);
258 create function count_tt1_v() returns int8 as
259 'select count(*) from tt1' language sql volatile;
261 create function count_tt1_s() returns int8 as
262 'select count(*) from tt1' language sql stable;
266 insert into tt1 values(1);
268 declare c1 cursor for select count_tt1_v(), count_tt1_s();
270 insert into tt1 values(2);
278 insert into tt1 values(1);
280 declare c2 cursor with hold for select count_tt1_v(), count_tt1_s();
282 insert into tt1 values(2);
290 drop function count_tt1_v();
291 drop function count_tt1_s();
294 -- Create a cursor with the BINARY option and check the pg_cursors view
296 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors;
297 DECLARE bc BINARY CURSOR FOR SELECT * FROM tenk1;
298 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors ORDER BY 1;
301 -- We should not see the portal that is created internally to
302 -- implement EXECUTE in pg_cursors
304 SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors;
308 SELECT name FROM pg_cursors ORDER BY 1;
310 SELECT name FROM pg_cursors ORDER BY 1;
312 DECLARE foo1 CURSOR WITH HOLD FOR SELECT 1;
313 DECLARE foo2 CURSOR WITHOUT HOLD FOR SELECT 1;
314 SELECT name FROM pg_cursors ORDER BY 1;
316 SELECT name FROM pg_cursors ORDER BY 1;
320 -- Tests for updatable cursors
323 CREATE TEMP TABLE uctest(f1 int, f2 text);
324 INSERT INTO uctest VALUES (1, 'one'), (2, 'two'), (3, 'three');
325 SELECT * FROM uctest;
327 -- Check DELETE WHERE CURRENT
329 DECLARE c1 CURSOR FOR SELECT * FROM uctest;
331 DELETE FROM uctest WHERE CURRENT OF c1;
332 -- should show deletion
333 SELECT * FROM uctest;
334 -- cursor did not move
336 -- cursor is insensitive
337 MOVE BACKWARD ALL IN c1;
340 -- should still see deletion
341 SELECT * FROM uctest;
343 -- Check UPDATE WHERE CURRENT; this time use FOR UPDATE
345 DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE;
347 UPDATE uctest SET f1 = 8 WHERE CURRENT OF c1;
348 SELECT * FROM uctest;
350 SELECT * FROM uctest;
352 -- Check repeated-update and update-then-delete cases
354 DECLARE c1 CURSOR FOR SELECT * FROM uctest;
356 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
357 SELECT * FROM uctest;
358 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
359 SELECT * FROM uctest;
360 -- insensitive cursor should not show effects of updates or deletes
361 FETCH RELATIVE 0 FROM c1;
362 DELETE FROM uctest WHERE CURRENT OF c1;
363 SELECT * FROM uctest;
364 DELETE FROM uctest WHERE CURRENT OF c1; -- no-op
365 SELECT * FROM uctest;
366 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op
367 SELECT * FROM uctest;
368 FETCH RELATIVE 0 FROM c1;
370 SELECT * FROM uctest;
373 DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE;
375 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
376 SELECT * FROM uctest;
377 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
378 SELECT * FROM uctest;
379 DELETE FROM uctest WHERE CURRENT OF c1;
380 SELECT * FROM uctest;
381 DELETE FROM uctest WHERE CURRENT OF c1; -- no-op
382 SELECT * FROM uctest;
383 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op
384 SELECT * FROM uctest;
385 --- sensitive cursors can't currently scroll back, so this is an error:
386 FETCH RELATIVE 0 FROM c1;
388 SELECT * FROM uctest;
390 -- Check inheritance cases
391 CREATE TEMP TABLE ucchild () inherits (uctest);
392 INSERT INTO ucchild values(100, 'hundred');
393 SELECT * FROM uctest;
396 DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE;
398 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
400 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
402 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
405 SELECT * FROM uctest;
407 -- Can update from a self-join, but only if FOR UPDATE says which to use
409 DECLARE c1 CURSOR FOR SELECT * FROM uctest a, uctest b WHERE a.f1 = b.f1 + 5;
411 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- fail
414 DECLARE c1 CURSOR FOR SELECT * FROM uctest a, uctest b WHERE a.f1 = b.f1 + 5 FOR UPDATE;
416 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- fail
419 DECLARE c1 CURSOR FOR SELECT * FROM uctest a, uctest b WHERE a.f1 = b.f1 + 5 FOR SHARE OF a;
421 UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1;
422 SELECT * FROM uctest;
425 -- Check various error cases
427 DELETE FROM uctest WHERE CURRENT OF c1; -- fail, no such cursor
428 DECLARE cx CURSOR WITH HOLD FOR SELECT * FROM uctest;
429 DELETE FROM uctest WHERE CURRENT OF cx; -- fail, can't use held cursor
431 DECLARE c CURSOR FOR SELECT * FROM tenk2;
432 DELETE FROM uctest WHERE CURRENT OF c; -- fail, cursor on wrong table
435 DECLARE c CURSOR FOR SELECT * FROM tenk2 FOR SHARE;
436 DELETE FROM uctest WHERE CURRENT OF c; -- fail, cursor on wrong table
439 DECLARE c CURSOR FOR SELECT * FROM tenk1 JOIN tenk2 USING (unique1);
440 DELETE FROM tenk1 WHERE CURRENT OF c; -- fail, cursor is on a join
443 DECLARE c CURSOR FOR SELECT f1,count(*) FROM uctest GROUP BY f1;
444 DELETE FROM uctest WHERE CURRENT OF c; -- fail, cursor is on aggregation
447 DECLARE c1 CURSOR FOR SELECT * FROM uctest;
448 DELETE FROM uctest WHERE CURRENT OF c1; -- fail, no current row
451 -- WHERE CURRENT OF may someday work with views, but today is not that day.
452 -- For now, just make sure it errors out cleanly.
453 CREATE TEMP VIEW ucview AS SELECT * FROM uctest;
454 CREATE RULE ucrule AS ON DELETE TO ucview DO INSTEAD
455 DELETE FROM uctest WHERE f1 = OLD.f1;
457 DECLARE c1 CURSOR FOR SELECT * FROM ucview;
459 DELETE FROM ucview WHERE CURRENT OF c1; -- fail, views not supported