1--
2-- Cursor regression tests
3--
4BEGIN;
5DECLARE foo1 SCROLL CURSOR FOR
6    SELECT
7        *
8    FROM
9        tenk1
10    ORDER BY
11        unique2;
12DECLARE foo2 SCROLL CURSOR FOR
13    SELECT
14        *
15    FROM
16        tenk2;
17DECLARE foo3 SCROLL CURSOR FOR
18    SELECT
19        *
20    FROM
21        tenk1
22    ORDER BY
23        unique2;
24DECLARE foo4 SCROLL CURSOR FOR
25    SELECT
26        *
27    FROM
28        tenk2;
29DECLARE foo5 SCROLL CURSOR FOR
30    SELECT
31        *
32    FROM
33        tenk1
34    ORDER BY
35        unique2;
36DECLARE foo6 SCROLL CURSOR FOR
37    SELECT
38        *
39    FROM
40        tenk2;
41DECLARE foo7 SCROLL CURSOR FOR
42    SELECT
43        *
44    FROM
45        tenk1
46    ORDER BY
47        unique2;
48DECLARE foo8 SCROLL CURSOR FOR
49    SELECT
50        *
51    FROM
52        tenk2;
53DECLARE foo9 SCROLL CURSOR FOR
54    SELECT
55        *
56    FROM
57        tenk1
58    ORDER BY
59        unique2;
60DECLARE foo10 SCROLL CURSOR FOR
61    SELECT
62        *
63    FROM
64        tenk2;
65DECLARE foo11 SCROLL CURSOR FOR
66    SELECT
67        *
68    FROM
69        tenk1
70    ORDER BY
71        unique2;
72DECLARE foo12 SCROLL CURSOR FOR
73    SELECT
74        *
75    FROM
76        tenk2;
77DECLARE foo13 SCROLL CURSOR FOR
78    SELECT
79        *
80    FROM
81        tenk1
82    ORDER BY
83        unique2;
84DECLARE foo14 SCROLL CURSOR FOR
85    SELECT
86        *
87    FROM
88        tenk2;
89DECLARE foo15 SCROLL CURSOR FOR
90    SELECT
91        *
92    FROM
93        tenk1
94    ORDER BY
95        unique2;
96DECLARE foo16 SCROLL CURSOR FOR
97    SELECT
98        *
99    FROM
100        tenk2;
101DECLARE foo17 SCROLL CURSOR FOR
102    SELECT
103        *
104    FROM
105        tenk1
106    ORDER BY
107        unique2;
108DECLARE foo18 SCROLL CURSOR FOR
109    SELECT
110        *
111    FROM
112        tenk2;
113DECLARE foo19 SCROLL CURSOR FOR
114    SELECT
115        *
116    FROM
117        tenk1
118    ORDER BY
119        unique2;
120DECLARE foo20 SCROLL CURSOR FOR
121    SELECT
122        *
123    FROM
124        tenk2;
125DECLARE foo21 SCROLL CURSOR FOR
126    SELECT
127        *
128    FROM
129        tenk1
130    ORDER BY
131        unique2;
132DECLARE foo22 SCROLL CURSOR FOR
133    SELECT
134        *
135    FROM
136        tenk2;
137DECLARE foo23 SCROLL CURSOR FOR
138    SELECT
139        *
140    FROM
141        tenk1
142    ORDER BY
143        unique2;
144FETCH 1 IN foo1;
145FETCH 2 IN foo2;
146FETCH 3 IN foo3;
147FETCH 4 IN foo4;
148FETCH 5 IN foo5;
149FETCH 6 IN foo6;
150FETCH 7 IN foo7;
151FETCH 8 IN foo8;
152FETCH 9 IN foo9;
153FETCH 10 IN foo10;
154FETCH 11 IN foo11;
155FETCH 12 IN foo12;
156FETCH 13 IN foo13;
157FETCH 14 IN foo14;
158FETCH 15 IN foo15;
159FETCH 16 IN foo16;
160FETCH 17 IN foo17;
161FETCH 18 IN foo18;
162FETCH 19 IN foo19;
163FETCH 20 IN foo20;
164FETCH 21 IN foo21;
165FETCH 22 IN foo22;
166FETCH 23 IN foo23;
167FETCH BACKWARD 1 IN foo23;
168FETCH BACKWARD 2 IN foo22;
169FETCH BACKWARD 3 IN foo21;
170FETCH BACKWARD 4 IN foo20;
171FETCH BACKWARD 5 IN foo19;
172FETCH BACKWARD 6 IN foo18;
173FETCH BACKWARD 7 IN foo17;
174FETCH BACKWARD 8 IN foo16;
175FETCH BACKWARD 9 IN foo15;
176FETCH BACKWARD 10 IN foo14;
177FETCH BACKWARD 11 IN foo13;
178FETCH BACKWARD 12 IN foo12;
179FETCH BACKWARD 13 IN foo11;
180FETCH BACKWARD 14 IN foo10;
181FETCH BACKWARD 15 IN foo9;
182FETCH BACKWARD 16 IN foo8;
183FETCH BACKWARD 17 IN foo7;
184FETCH BACKWARD 18 IN foo6;
185FETCH BACKWARD 19 IN foo5;
186FETCH BACKWARD 20 IN foo4;
187FETCH BACKWARD 21 IN foo3;
188FETCH BACKWARD 22 IN foo2;
189FETCH BACKWARD 23 IN foo1;
190CLOSE foo1;
191CLOSE foo2;
192CLOSE foo3;
193CLOSE foo4;
194CLOSE foo5;
195CLOSE foo6;
196CLOSE foo7;
197CLOSE foo8;
198CLOSE foo9;
199CLOSE foo10;
200CLOSE foo11;
201CLOSE foo12;
202-- leave some cursors open, to test that auto-close works.
203-- record this in the system view as well (don't query the time field there
204-- however)
205SELECT
206    name,
207    statement,
208    is_holdable,
209    is_binary,
210    is_scrollable
211FROM
212    pg_cursors
213ORDER BY
214    1;
215END;
216SELECT
217    name,
218    statement,
219    is_holdable,
220    is_binary,
221    is_scrollable
222FROM
223    pg_cursors;
224--
225-- NO SCROLL disallows backward fetching
226--
227BEGIN;
228DECLARE foo24 NO SCROLL CURSOR FOR
229    SELECT
230        *
231    FROM
232        tenk1
233    ORDER BY
234        unique2;
235FETCH 1 FROM foo24;
236FETCH BACKWARD 1 FROM foo24;
237-- should fail
238END;
239--
240-- Cursors outside transaction blocks
241--
242SELECT
243    name,
244    statement,
245    is_holdable,
246    is_binary,
247    is_scrollable
248FROM
249    pg_cursors;
250BEGIN;
251DECLARE foo25 SCROLL CURSOR WITH HOLD FOR
252    SELECT
253        *
254    FROM
255        tenk2;
256FETCH FROM foo25;
257FETCH FROM foo25;
258COMMIT;
259
260FETCH FROM foo25;
261
262FETCH BACKWARD FROM foo25;
263
264FETCH ABSOLUTE - 1 FROM foo25;
265
266SELECT
267    name,
268    statement,
269    is_holdable,
270    is_binary,
271    is_scrollable
272FROM
273    pg_cursors;
274
275CLOSE foo25;
276
277--
278-- ROLLBACK should close holdable cursors
279--
280BEGIN;
281DECLARE foo26 CURSOR WITH HOLD FOR
282    SELECT
283        *
284    FROM
285        tenk1
286    ORDER BY
287        unique2;
288ROLLBACK;
289
290-- should fail
291FETCH
292FROM
293    foo26;
294
295--
296-- Parameterized DECLARE needs to insert param values into the cursor portal
297--
298BEGIN;
299CREATE FUNCTION declares_cursor (text)
300    RETURNS void
301    AS 'DECLARE c CURSOR FOR SELECT stringu1 FROM tenk1 WHERE stringu1 LIKE $1;'
302    LANGUAGE SQL;
303SELECT
304    declares_cursor ('AB%');
305FETCH ALL FROM c;
306ROLLBACK;
307
308--
309-- Test behavior of both volatile and stable functions inside a cursor;
310-- in particular we want to see what happens during commit of a holdable
311-- cursor
312--
313CREATE temp TABLE tt1 (
314    f1 int
315);
316
317CREATE FUNCTION count_tt1_v ()
318    RETURNS int8
319    AS 'select count(*) from tt1'
320    LANGUAGE sql
321    VOLATILE;
322
323CREATE FUNCTION count_tt1_s ()
324    RETURNS int8
325    AS 'select count(*) from tt1'
326    LANGUAGE sql
327    STABLE;
328
329BEGIN;
330INSERT INTO tt1
331    VALUES (1);
332DECLARE c1 CURSOR FOR
333    SELECT
334        count_tt1_v (),
335        count_tt1_s ();
336INSERT INTO tt1
337    VALUES (2);
338FETCH ALL FROM c1;
339ROLLBACK;
340
341BEGIN;
342INSERT INTO tt1
343    VALUES (1);
344DECLARE c2 CURSOR WITH hold FOR
345    SELECT
346        count_tt1_v (
347),
348        count_tt1_s ();
349INSERT INTO tt1
350    VALUES (2);
351COMMIT;
352
353DELETE FROM tt1;
354
355FETCH ALL FROM c2;
356
357DROP FUNCTION count_tt1_v ();
358
359DROP FUNCTION count_tt1_s ();
360
361-- Create a cursor with the BINARY option and check the pg_cursors view
362BEGIN;
363SELECT
364    name,
365    statement,
366    is_holdable,
367    is_binary,
368    is_scrollable
369FROM
370    pg_cursors;
371DECLARE bc BINARY CURSOR FOR
372    SELECT
373        *
374    FROM
375        tenk1;
376SELECT
377    name,
378    statement,
379    is_holdable,
380    is_binary,
381    is_scrollable
382FROM
383    pg_cursors
384ORDER BY
385    1;
386ROLLBACK;
387
388-- We should not see the portal that is created internally to
389-- implement EXECUTE in pg_cursors
390PREPARE cprep AS
391SELECT
392    name,
393    statement,
394    is_holdable,
395    is_binary,
396    is_scrollable
397FROM
398    pg_cursors;
399
400EXECUTE cprep;
401
402-- test CLOSE ALL;
403SELECT
404    name
405FROM
406    pg_cursors
407ORDER BY
408    1;
409
410CLOSE ALL;
411
412SELECT
413    name
414FROM
415    pg_cursors
416ORDER BY
417    1;
418
419BEGIN;
420DECLARE foo1 CURSOR WITH HOLD FOR
421    SELECT
422        1;
423DECLARE foo2 CURSOR WITHOUT HOLD FOR
424    SELECT
425        1;
426SELECT
427    name
428FROM
429    pg_cursors
430ORDER BY
431    1;
432CLOSE ALL;
433SELECT
434    name
435FROM
436    pg_cursors
437ORDER BY
438    1;
439COMMIT;
440
441--
442-- Tests for updatable cursors
443--
444CREATE TEMP TABLE uctest (
445    f1 int,
446    f2 text
447);
448
449INSERT INTO uctest
450    VALUES (1, 'one'), (2, 'two'), (3, 'three');
451
452SELECT
453    *
454FROM
455    uctest;
456
457-- Check DELETE WHERE CURRENT
458BEGIN;
459DECLARE c1 CURSOR FOR
460    SELECT
461        *
462    FROM
463        uctest;
464FETCH 2 FROM c1;
465DELETE FROM uctest
466WHERE CURRENT OF c1;
467-- should show deletion
468SELECT
469    *
470FROM
471    uctest;
472-- cursor did not move
473FETCH ALL
474FROM
475    c1;
476-- cursor is insensitive
477MOVE BACKWARD ALL IN c1;
478FETCH ALL FROM c1;
479COMMIT;
480
481-- should still see deletion
482SELECT
483    *
484FROM
485    uctest;
486
487-- Check UPDATE WHERE CURRENT; this time use FOR UPDATE
488BEGIN;
489DECLARE c1 CURSOR FOR
490    SELECT
491        *
492    FROM
493        uctest
494    FOR UPDATE;
495FETCH c1;
496UPDATE
497    uctest
498SET
499    f1 = 8
500WHERE
501    CURRENT OF c1;
502SELECT
503    *
504FROM
505    uctest;
506COMMIT;
507
508SELECT
509    *
510FROM
511    uctest;
512
513-- Check repeated-update and update-then-delete cases
514BEGIN;
515DECLARE c1 CURSOR FOR
516    SELECT
517        *
518    FROM
519        uctest;
520FETCH c1;
521UPDATE
522    uctest
523SET
524    f1 = f1 + 10
525WHERE
526    CURRENT OF c1;
527SELECT
528    *
529FROM
530    uctest;
531UPDATE
532    uctest
533SET
534    f1 = f1 + 10
535WHERE
536    CURRENT OF c1;
537SELECT
538    *
539FROM
540    uctest;
541-- insensitive cursor should not show effects of updates or deletes
542FETCH RELATIVE 0
543FROM
544    c1;
545DELETE FROM uctest
546WHERE CURRENT OF c1;
547SELECT
548    *
549FROM
550    uctest;
551DELETE FROM uctest
552WHERE CURRENT OF c1;
553-- no-op
554SELECT
555    *
556FROM
557    uctest;
558UPDATE
559    uctest
560SET
561    f1 = f1 + 10
562WHERE
563    CURRENT OF c1;
564-- no-op
565SELECT
566    *
567FROM
568    uctest;
569FETCH RELATIVE 0 FROM c1;
570ROLLBACK;
571
572SELECT
573    *
574FROM
575    uctest;
576
577BEGIN;
578DECLARE c1 CURSOR FOR
579    SELECT
580        *
581    FROM
582        uctest
583    FOR UPDATE;
584FETCH c1;
585UPDATE
586    uctest
587SET
588    f1 = f1 + 10
589WHERE
590    CURRENT OF c1;
591SELECT
592    *
593FROM
594    uctest;
595UPDATE
596    uctest
597SET
598    f1 = f1 + 10
599WHERE
600    CURRENT OF c1;
601SELECT
602    *
603FROM
604    uctest;
605DELETE FROM uctest
606WHERE CURRENT OF c1;
607SELECT
608    *
609FROM
610    uctest;
611DELETE FROM uctest
612WHERE CURRENT OF c1;
613-- no-op
614SELECT
615    *
616FROM
617    uctest;
618UPDATE
619    uctest
620SET
621    f1 = f1 + 10
622WHERE
623    CURRENT OF c1;
624-- no-op
625SELECT
626    *
627FROM
628    uctest;
629--- sensitive cursors can't currently scroll back, so this is an error:
630FETCH RELATIVE 0
631FROM
632    c1;
633ROLLBACK;
634
635SELECT
636    *
637FROM
638    uctest;
639
640-- Check inheritance cases
641CREATE TEMP TABLE ucchild ()
642INHERITS (
643    uctest
644);
645
646INSERT INTO ucchild
647    VALUES (100, 'hundred');
648
649SELECT
650    *
651FROM
652    uctest;
653
654BEGIN;
655DECLARE c1 CURSOR FOR
656    SELECT
657        *
658    FROM
659        uctest
660    FOR UPDATE;
661FETCH 1 FROM c1;
662UPDATE
663    uctest
664SET
665    f1 = f1 + 10
666WHERE
667    CURRENT OF c1;
668FETCH 1 FROM c1;
669UPDATE
670    uctest
671SET
672    f1 = f1 + 10
673WHERE
674    CURRENT OF c1;
675FETCH 1 FROM c1;
676UPDATE
677    uctest
678SET
679    f1 = f1 + 10
680WHERE
681    CURRENT OF c1;
682FETCH 1 FROM c1;
683COMMIT;
684
685SELECT
686    *
687FROM
688    uctest;
689
690-- Can update from a self-join, but only if FOR UPDATE says which to use
691BEGIN;
692DECLARE c1 CURSOR FOR
693    SELECT
694        *
695    FROM
696        uctest a,
697        uctest b
698    WHERE
699        a.f1 = b.f1 + 5;
700FETCH 1 FROM c1;
701UPDATE
702    uctest
703SET
704    f1 = f1 + 10
705WHERE
706    CURRENT OF c1;
707-- fail
708ROLLBACK;
709
710BEGIN;
711DECLARE c1 CURSOR FOR
712    SELECT
713        *
714    FROM
715        uctest a,
716        uctest b
717    WHERE
718        a.f1 = b.f1 + 5
719    FOR UPDATE;
720FETCH 1 FROM c1;
721UPDATE
722    uctest
723SET
724    f1 = f1 + 10
725WHERE
726    CURRENT OF c1;
727-- fail
728ROLLBACK;
729
730BEGIN;
731DECLARE c1 CURSOR FOR
732    SELECT
733        *
734    FROM
735        uctest a,
736        uctest b
737    WHERE
738        a.f1 = b.f1 + 5 FOR SHARE OF a;
739FETCH 1 FROM c1;
740UPDATE
741    uctest
742SET
743    f1 = f1 + 10
744WHERE
745    CURRENT OF c1;
746SELECT
747    *
748FROM
749    uctest;
750ROLLBACK;
751
752-- Check various error cases
753DELETE FROM uctest
754WHERE CURRENT OF c1;
755
756-- fail, no such cursor
757DECLARE cx CURSOR WITH HOLD FOR
758    SELECT
759        *
760    FROM
761        uctest;
762
763DELETE FROM uctest
764WHERE CURRENT OF cx;
765
766-- fail, can't use held cursor
767BEGIN;
768DECLARE c CURSOR FOR
769    SELECT
770        *
771    FROM
772        tenk2;
773DELETE FROM uctest
774WHERE CURRENT OF c;
775-- fail, cursor on wrong table
776ROLLBACK;
777
778BEGIN;
779DECLARE c CURSOR FOR
780    SELECT
781        *
782    FROM
783        tenk2 FOR SHARE;
784DELETE FROM uctest
785WHERE CURRENT OF c;
786-- fail, cursor on wrong table
787ROLLBACK;
788
789BEGIN;
790DECLARE c CURSOR FOR
791    SELECT
792        *
793    FROM
794        tenk1
795        JOIN tenk2 USING (unique1);
796DELETE FROM tenk1
797WHERE CURRENT OF c;
798-- fail, cursor is on a join
799ROLLBACK;
800
801BEGIN;
802DECLARE c CURSOR FOR
803    SELECT
804        f1,
805        count(*)
806    FROM
807        uctest
808    GROUP BY
809        f1;
810DELETE FROM uctest
811WHERE CURRENT OF c;
812-- fail, cursor is on aggregation
813ROLLBACK;
814
815BEGIN;
816DECLARE c1 CURSOR FOR
817    SELECT
818        *
819    FROM
820        uctest;
821DELETE FROM uctest
822WHERE CURRENT OF c1;
823-- fail, no current row
824ROLLBACK;
825
826BEGIN;
827DECLARE c1 CURSOR FOR
828    SELECT
829        MIN(f1)
830    FROM
831        uctest
832    FOR UPDATE;
833ROLLBACK;
834
835-- WHERE CURRENT OF may someday work with views, but today is not that day.
836-- For now, just make sure it errors out cleanly.
837CREATE TEMP VIEW ucview AS
838SELECT
839    *
840FROM
841    uctest;
842
843CREATE RULE ucrule AS ON DELETE TO ucview
844    DO INSTEAD
845    DELETE FROM uctest
846    WHERE f1 = OLD.f1;
847
848BEGIN;
849DECLARE c1 CURSOR FOR
850    SELECT
851        *
852    FROM
853        ucview;
854FETCH FROM c1;
855DELETE FROM ucview
856WHERE CURRENT OF c1;
857-- fail, views not supported
858ROLLBACK;
859
860-- Check WHERE CURRENT OF with an index-only scan
861BEGIN;
862EXPLAIN (
863    COSTS OFF
864) DECLARE c1 CURSOR FOR
865    SELECT
866        stringu1
867    FROM
868        onek
869    WHERE
870        stringu1 = 'DZAAAA';
871DECLARE c1 CURSOR FOR
872    SELECT
873        stringu1
874    FROM
875        onek
876    WHERE
877        stringu1 = 'DZAAAA';
878FETCH FROM c1;
879DELETE FROM onek
880WHERE CURRENT OF c1;
881SELECT
882    stringu1
883FROM
884    onek
885WHERE
886    stringu1 = 'DZAAAA';
887ROLLBACK;
888
889-- Check behavior with rewinding to a previous child scan node,
890-- as per bug #15395
891BEGIN;
892CREATE TABLE current_check (
893    currentid int,
894    payload text
895);
896CREATE TABLE current_check_1 ()
897INHERITS (
898    current_check
899);
900CREATE TABLE current_check_2 ()
901INHERITS (
902    current_check
903);
904INSERT INTO current_check_1
905SELECT
906    i,
907    'p' || i
908FROM
909    generate_series(1, 9) i;
910INSERT INTO current_check_2
911SELECT
912    i,
913    'P' || i
914FROM
915    generate_series(10, 19) i;
916DECLARE c1 SCROLL CURSOR FOR
917    SELECT
918        *
919    FROM
920        current_check;
921-- This tests the fetch-backwards code path
922FETCH ABSOLUTE 12
923FROM
924    c1;
925FETCH ABSOLUTE 8 FROM c1;
926DELETE FROM current_check
927WHERE CURRENT OF c1
928RETURNING
929    *;
930-- This tests the ExecutorRewind code path
931FETCH ABSOLUTE 13
932FROM
933    c1;
934FETCH ABSOLUTE 1 FROM c1;
935DELETE FROM current_check
936WHERE CURRENT OF c1
937RETURNING
938    *;
939SELECT
940    *
941FROM
942    current_check;
943ROLLBACK;
944
945-- Make sure snapshot management works okay, per bug report in
946-- 235395b90909301035v7228ce63q392931f15aa74b31@mail.gmail.com
947BEGIN;
948SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
949CREATE TABLE CURSOR (
950    a int
951);
952INSERT INTO CURSOR
953    VALUES (1);
954DECLARE c1 NO SCROLL CURSOR FOR
955    SELECT
956        *
957    FROM
958        CURSOR
959    FOR UPDATE;
960UPDATE
961    CURSOR
962SET
963    a = 2;
964FETCH ALL FROM c1;
965COMMIT;
966
967DROP TABLE CURSOR;
968
969-- Check rewinding a cursor containing a stable function in LIMIT,
970-- per bug report in 8336843.9833.1399385291498.JavaMail.root@quick
971BEGIN;
972CREATE FUNCTION nochange (int)
973    RETURNS int
974    AS 'select $1 limit 1'
975    LANGUAGE sql
976    STABLE;
977DECLARE c CURSOR FOR
978    SELECT
979        *
980    FROM
981        int8_tbl
982    LIMIT nochange (3);
983FETCH ALL FROM c;
984MOVE BACKWARD ALL IN c;
985FETCH ALL FROM c;
986ROLLBACK;
987
988-- Check handling of non-backwards-scan-capable plans with scroll cursors
989BEGIN;
990EXPLAIN (
991    COSTS OFF
992) DECLARE c1 CURSOR FOR
993    SELECT
994        (
995            SELECT
996                42) AS x;
997EXPLAIN (
998    COSTS OFF
999) DECLARE c1 SCROLL CURSOR FOR
1000    SELECT
1001        (
1002            SELECT
1003                42) AS x;
1004DECLARE c1 SCROLL CURSOR FOR
1005    SELECT
1006        (
1007            SELECT
1008                42) AS x;
1009FETCH ALL IN c1;
1010FETCH BACKWARD ALL IN c1;
1011ROLLBACK;
1012
1013BEGIN;
1014EXPLAIN (
1015    COSTS OFF
1016) DECLARE c2 CURSOR FOR
1017    SELECT
1018        generate_series(1, 3) AS g;
1019EXPLAIN (
1020    COSTS OFF
1021) DECLARE c2 SCROLL CURSOR FOR
1022    SELECT
1023        generate_series(1, 3) AS g;
1024DECLARE c2 SCROLL CURSOR FOR
1025    SELECT
1026        generate_series(1, 3) AS g;
1027FETCH ALL IN c2;
1028FETCH BACKWARD ALL IN c2;
1029ROLLBACK;
1030
1031