1 CREATE TABLE rngfunc2(rngfuncid int, f2 int);
2 INSERT INTO rngfunc2 VALUES(1, 11);
3 INSERT INTO rngfunc2 VALUES(2, 22);
4 INSERT INTO rngfunc2 VALUES(1, 111);
5 CREATE FUNCTION rngfunct(int) returns setof rngfunc2 as 'SELECT * FROM rngfunc2 WHERE rngfuncid = $1 ORDER BY f2;' LANGUAGE SQL;
6 -- function with ORDINALITY
7 select * from rngfunct(1) with ordinality as z(a,b,ord);
14 select * from rngfunct(1) with ordinality as z(a,b,ord) where b > 100; -- ordinal 2, not 1
20 -- ordinality vs. column names and types
21 select a,b,ord from rngfunct(1) with ordinality as z(a,b,ord);
28 select a,ord from unnest(array['a','b']) with ordinality as z(a,ord);
35 select * from unnest(array['a','b']) with ordinality as z(a,ord);
42 select a,ord from unnest(array[1.0::float8]) with ordinality as z(a,ord);
48 select * from unnest(array[1.0::float8]) with ordinality as z(a,ord);
54 select row_to_json(s.*) from generate_series(11,14) with ordinality s;
56 -------------------------
57 {"s":11,"ordinality":1}
58 {"s":12,"ordinality":2}
59 {"s":13,"ordinality":3}
60 {"s":14,"ordinality":4}
63 -- ordinality vs. views
64 create temporary view vw_ord as select * from (values (1)) v(n) join rngfunct(1) with ordinality as z(a,b,ord) on (n=ord);
71 select definition from pg_views where viewname='vw_ord';
73 -------------------------------------------------------------------------
78 FROM (( VALUES (1)) v(n) +
79 JOIN rngfunct(1) WITH ORDINALITY z(a, b, ord) ON ((v.n = z.ord)));
84 select * from rows from(rngfunct(1),rngfunct(2)) with ordinality as z(a,b,c,d,ord);
86 ---+-----+---+----+-----
91 create temporary view vw_ord as select * from (values (1)) v(n) join rows from(rngfunct(1),rngfunct(2)) with ordinality as z(a,b,c,d,ord) on (n=ord);
93 n | a | b | c | d | ord
94 ---+---+----+---+----+-----
95 1 | 1 | 11 | 2 | 22 | 1
98 select definition from pg_views where viewname='vw_ord';
100 -------------------------------------------------------------------------------------------------------
107 FROM (( VALUES (1)) v(n) +
108 JOIN ROWS FROM(rngfunct(1), rngfunct(2)) WITH ORDINALITY z(a, b, c, d, ord) ON ((v.n = z.ord)));
112 -- expansions of unnest()
113 select * from unnest(array[10,20],array['foo','bar'],array[1.0]);
114 unnest | unnest | unnest
115 --------+--------+--------
120 select * from unnest(array[10,20],array['foo','bar'],array[1.0]) with ordinality as z(a,b,c,ord);
122 ----+-----+-----+-----
127 select * from rows from(unnest(array[10,20],array['foo','bar'],array[1.0])) with ordinality as z(a,b,c,ord);
129 ----+-----+-----+-----
134 select * from rows from(unnest(array[10,20],array['foo','bar']), generate_series(101,102)) with ordinality as z(a,b,c,ord);
136 ----+-----+-----+-----
141 create temporary view vw_ord as select * from unnest(array[10,20],array['foo','bar'],array[1.0]) as z(a,b,c);
142 select * from vw_ord;
149 select definition from pg_views where viewname='vw_ord';
151 ----------------------------------------------------------------------------------------
155 FROM UNNEST(ARRAY[10, 20], ARRAY['foo'::text, 'bar'::text], ARRAY[1.0]) z(a, b, c);
159 create temporary view vw_ord as select * from rows from(unnest(array[10,20],array['foo','bar'],array[1.0])) as z(a,b,c);
160 select * from vw_ord;
167 select definition from pg_views where viewname='vw_ord';
169 ----------------------------------------------------------------------------------------
173 FROM UNNEST(ARRAY[10, 20], ARRAY['foo'::text, 'bar'::text], ARRAY[1.0]) z(a, b, c);
177 create temporary view vw_ord as select * from rows from(unnest(array[10,20],array['foo','bar']), generate_series(1,2)) as z(a,b,c);
178 select * from vw_ord;
185 select definition from pg_views where viewname='vw_ord';
187 ----------------------------------------------------------------------------------------------------------------------
191 FROM ROWS FROM(unnest(ARRAY[10, 20]), unnest(ARRAY['foo'::text, 'bar'::text]), generate_series(1, 2)) z(a, b, c);
195 -- ordinality and multiple functions vs. rewind and reverse scan
197 declare rf_cur scroll cursor for select * from rows from(generate_series(1,5),generate_series(1,2)) with ordinality as g(i,j,o);
198 fetch all from rf_cur;
208 fetch backward all from rf_cur;
218 fetch all from rf_cur;
228 fetch next from rf_cur;
233 fetch next from rf_cur;
238 fetch prior from rf_cur;
244 fetch absolute 1 from rf_cur;
250 fetch next from rf_cur;
256 fetch next from rf_cur;
262 fetch next from rf_cur;
268 fetch prior from rf_cur;
274 fetch prior from rf_cur;
280 fetch prior from rf_cur;
287 -- function with implicit LATERAL
288 select * from rngfunc2, rngfunct(rngfunc2.rngfuncid) z where rngfunc2.f2 = z.f2;
289 rngfuncid | f2 | rngfuncid | f2
290 -----------+-----+-----------+-----
296 -- function with implicit LATERAL and explicit ORDINALITY
297 select * from rngfunc2, rngfunct(rngfunc2.rngfuncid) with ordinality as z(rngfuncid,f2,ord) where rngfunc2.f2 = z.f2;
298 rngfuncid | f2 | rngfuncid | f2 | ord
299 -----------+-----+-----------+-----+-----
302 1 | 111 | 1 | 111 | 2
305 -- function in subselect
306 select * from rngfunc2 where f2 in (select f2 from rngfunct(rngfunc2.rngfuncid) z where z.rngfuncid = rngfunc2.rngfuncid) ORDER BY 1,2;
314 -- function in subselect
315 select * from rngfunc2 where f2 in (select f2 from rngfunct(1) z where z.rngfuncid = rngfunc2.rngfuncid) ORDER BY 1,2;
322 -- function in subselect
323 select * from rngfunc2 where f2 in (select f2 from rngfunct(rngfunc2.rngfuncid) z where z.rngfuncid = 1) ORDER BY 1,2;
331 select rngfunct.rngfuncid, rngfunct.f2 from rngfunct(sin(pi()/2)::int) ORDER BY 1,2;
338 CREATE TABLE rngfunc (rngfuncid int, rngfuncsubid int, rngfuncname text, primary key(rngfuncid,rngfuncsubid));
339 INSERT INTO rngfunc VALUES(1,1,'Joe');
340 INSERT INTO rngfunc VALUES(1,2,'Ed');
341 INSERT INTO rngfunc VALUES(2,1,'Mary');
342 -- sql, proretset = f, prorettype = b
343 CREATE FUNCTION getrngfunc1(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL;
344 SELECT * FROM getrngfunc1(1) AS t1;
350 SELECT * FROM getrngfunc1(1) WITH ORDINALITY AS t1(v,o);
356 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc1(1);
357 SELECT * FROM vw_getrngfunc;
363 DROP VIEW vw_getrngfunc;
364 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc1(1) WITH ORDINALITY as t1(v,o);
365 SELECT * FROM vw_getrngfunc;
371 DROP VIEW vw_getrngfunc;
372 -- sql, proretset = t, prorettype = b
373 CREATE FUNCTION getrngfunc2(int) RETURNS setof int AS 'SELECT rngfuncid FROM rngfunc WHERE rngfuncid = $1;' LANGUAGE SQL;
374 SELECT * FROM getrngfunc2(1) AS t1;
381 SELECT * FROM getrngfunc2(1) WITH ORDINALITY AS t1(v,o);
388 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc2(1);
389 SELECT * FROM vw_getrngfunc;
396 DROP VIEW vw_getrngfunc;
397 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc2(1) WITH ORDINALITY AS t1(v,o);
398 SELECT * FROM vw_getrngfunc;
405 DROP VIEW vw_getrngfunc;
406 -- sql, proretset = t, prorettype = b
407 CREATE FUNCTION getrngfunc3(int) RETURNS setof text AS 'SELECT rngfuncname FROM rngfunc WHERE rngfuncid = $1;' LANGUAGE SQL;
408 SELECT * FROM getrngfunc3(1) AS t1;
415 SELECT * FROM getrngfunc3(1) WITH ORDINALITY AS t1(v,o);
422 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc3(1);
423 SELECT * FROM vw_getrngfunc;
430 DROP VIEW vw_getrngfunc;
431 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc3(1) WITH ORDINALITY AS t1(v,o);
432 SELECT * FROM vw_getrngfunc;
439 DROP VIEW vw_getrngfunc;
440 -- sql, proretset = f, prorettype = c
441 CREATE FUNCTION getrngfunc4(int) RETURNS rngfunc AS 'SELECT * FROM rngfunc WHERE rngfuncid = $1;' LANGUAGE SQL;
442 SELECT * FROM getrngfunc4(1) AS t1;
443 rngfuncid | rngfuncsubid | rngfuncname
444 -----------+--------------+-------------
448 SELECT * FROM getrngfunc4(1) WITH ORDINALITY AS t1(a,b,c,o);
454 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc4(1);
455 SELECT * FROM vw_getrngfunc;
456 rngfuncid | rngfuncsubid | rngfuncname
457 -----------+--------------+-------------
461 DROP VIEW vw_getrngfunc;
462 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc4(1) WITH ORDINALITY AS t1(a,b,c,o);
463 SELECT * FROM vw_getrngfunc;
469 DROP VIEW vw_getrngfunc;
470 -- sql, proretset = t, prorettype = c
471 CREATE FUNCTION getrngfunc5(int) RETURNS setof rngfunc AS 'SELECT * FROM rngfunc WHERE rngfuncid = $1;' LANGUAGE SQL;
472 SELECT * FROM getrngfunc5(1) AS t1;
473 rngfuncid | rngfuncsubid | rngfuncname
474 -----------+--------------+-------------
479 SELECT * FROM getrngfunc5(1) WITH ORDINALITY AS t1(a,b,c,o);
486 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc5(1);
487 SELECT * FROM vw_getrngfunc;
488 rngfuncid | rngfuncsubid | rngfuncname
489 -----------+--------------+-------------
494 DROP VIEW vw_getrngfunc;
495 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc5(1) WITH ORDINALITY AS t1(a,b,c,o);
496 SELECT * FROM vw_getrngfunc;
503 DROP VIEW vw_getrngfunc;
504 -- sql, proretset = f, prorettype = record
505 CREATE FUNCTION getrngfunc6(int) RETURNS RECORD AS 'SELECT * FROM rngfunc WHERE rngfuncid = $1;' LANGUAGE SQL;
506 SELECT * FROM getrngfunc6(1) AS t1(rngfuncid int, rngfuncsubid int, rngfuncname text);
507 rngfuncid | rngfuncsubid | rngfuncname
508 -----------+--------------+-------------
512 SELECT * FROM ROWS FROM( getrngfunc6(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text) ) WITH ORDINALITY;
513 rngfuncid | rngfuncsubid | rngfuncname | ordinality
514 -----------+--------------+-------------+------------
518 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc6(1) AS
519 (rngfuncid int, rngfuncsubid int, rngfuncname text);
520 SELECT * FROM vw_getrngfunc;
521 rngfuncid | rngfuncsubid | rngfuncname
522 -----------+--------------+-------------
526 DROP VIEW vw_getrngfunc;
527 CREATE VIEW vw_getrngfunc AS
528 SELECT * FROM ROWS FROM( getrngfunc6(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text) )
530 SELECT * FROM vw_getrngfunc;
531 rngfuncid | rngfuncsubid | rngfuncname | ordinality
532 -----------+--------------+-------------+------------
536 DROP VIEW vw_getrngfunc;
537 -- sql, proretset = t, prorettype = record
538 CREATE FUNCTION getrngfunc7(int) RETURNS setof record AS 'SELECT * FROM rngfunc WHERE rngfuncid = $1;' LANGUAGE SQL;
539 SELECT * FROM getrngfunc7(1) AS t1(rngfuncid int, rngfuncsubid int, rngfuncname text);
540 rngfuncid | rngfuncsubid | rngfuncname
541 -----------+--------------+-------------
546 SELECT * FROM ROWS FROM( getrngfunc7(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text) ) WITH ORDINALITY;
547 rngfuncid | rngfuncsubid | rngfuncname | ordinality
548 -----------+--------------+-------------+------------
553 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc7(1) AS
554 (rngfuncid int, rngfuncsubid int, rngfuncname text);
555 SELECT * FROM vw_getrngfunc;
556 rngfuncid | rngfuncsubid | rngfuncname
557 -----------+--------------+-------------
562 DROP VIEW vw_getrngfunc;
563 CREATE VIEW vw_getrngfunc AS
564 SELECT * FROM ROWS FROM( getrngfunc7(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text) )
566 SELECT * FROM vw_getrngfunc;
567 rngfuncid | rngfuncsubid | rngfuncname | ordinality
568 -----------+--------------+-------------+------------
573 DROP VIEW vw_getrngfunc;
574 -- plpgsql, proretset = f, prorettype = b
575 CREATE FUNCTION getrngfunc8(int) RETURNS int AS 'DECLARE rngfuncint int; BEGIN SELECT rngfuncid into rngfuncint FROM rngfunc WHERE rngfuncid = $1; RETURN rngfuncint; END;' LANGUAGE plpgsql;
576 SELECT * FROM getrngfunc8(1) AS t1;
582 SELECT * FROM getrngfunc8(1) WITH ORDINALITY AS t1(v,o);
588 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc8(1);
589 SELECT * FROM vw_getrngfunc;
595 DROP VIEW vw_getrngfunc;
596 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc8(1) WITH ORDINALITY AS t1(v,o);
597 SELECT * FROM vw_getrngfunc;
603 DROP VIEW vw_getrngfunc;
604 -- plpgsql, proretset = f, prorettype = c
605 CREATE FUNCTION getrngfunc9(int) RETURNS rngfunc AS 'DECLARE rngfunctup rngfunc%ROWTYPE; BEGIN SELECT * into rngfunctup FROM rngfunc WHERE rngfuncid = $1; RETURN rngfunctup; END;' LANGUAGE plpgsql;
606 SELECT * FROM getrngfunc9(1) AS t1;
607 rngfuncid | rngfuncsubid | rngfuncname
608 -----------+--------------+-------------
612 SELECT * FROM getrngfunc9(1) WITH ORDINALITY AS t1(a,b,c,o);
618 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc9(1);
619 SELECT * FROM vw_getrngfunc;
620 rngfuncid | rngfuncsubid | rngfuncname
621 -----------+--------------+-------------
625 DROP VIEW vw_getrngfunc;
626 CREATE VIEW vw_getrngfunc AS SELECT * FROM getrngfunc9(1) WITH ORDINALITY AS t1(a,b,c,o);
627 SELECT * FROM vw_getrngfunc;
633 DROP VIEW vw_getrngfunc;
634 -- mix 'n match kinds, to exercise expandRTE and related logic
635 select * from rows from(getrngfunc1(1),getrngfunc2(1),getrngfunc3(1),getrngfunc4(1),getrngfunc5(1),
636 getrngfunc6(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text),
637 getrngfunc7(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text),
638 getrngfunc8(1),getrngfunc9(1))
639 with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u);
640 a | b | c | d | e | f | g | h | i | j | k | l | m | o | p | q | r | s | t | u
641 ---+---+-----+---+---+-----+---+---+-----+---+---+-----+---+---+-----+---+---+---+-----+---
642 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | 1 | Joe | 1
643 | 1 | Ed | | | | 1 | 2 | Ed | | | | 1 | 2 | Ed | | | | | 2
646 select * from rows from(getrngfunc9(1),getrngfunc8(1),
647 getrngfunc7(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text),
648 getrngfunc6(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text),
649 getrngfunc5(1),getrngfunc4(1),getrngfunc3(1),getrngfunc2(1),getrngfunc1(1))
650 with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u);
651 a | b | c | d | e | f | g | h | i | j | k | l | m | o | p | q | r | s | t | u
652 ---+---+-----+---+---+---+-----+---+---+-----+---+---+-----+---+---+-----+-----+---+---+---
653 1 | 1 | Joe | 1 | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | Joe | 1 | 1 | 1
654 | | | | 1 | 2 | Ed | | | | 1 | 2 | Ed | | | | Ed | 1 | | 2
657 create temporary view vw_rngfunc as
658 select * from rows from(getrngfunc9(1),
659 getrngfunc7(1) AS (rngfuncid int, rngfuncsubid int, rngfuncname text),
661 with ordinality as t1(a,b,c,d,e,f,g,n);
662 select * from vw_rngfunc;
663 a | b | c | d | e | f | g | n
664 ---+---+-----+---+---+-----+---+---
665 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1
666 | | | 1 | 2 | Ed | | 2
669 select pg_get_viewdef('vw_rngfunc');
671 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
680 FROM ROWS FROM(getrngfunc9(1), getrngfunc7(1) AS (rngfuncid integer, rngfuncsubid integer, rngfuncname text), getrngfunc1(1)) WITH ORDINALITY t1(a, b, c, d, e, f, g, n);
683 drop view vw_rngfunc;
684 DROP FUNCTION getrngfunc1(int);
685 DROP FUNCTION getrngfunc2(int);
686 DROP FUNCTION getrngfunc3(int);
687 DROP FUNCTION getrngfunc4(int);
688 DROP FUNCTION getrngfunc5(int);
689 DROP FUNCTION getrngfunc6(int);
690 DROP FUNCTION getrngfunc7(int);
691 DROP FUNCTION getrngfunc8(int);
692 DROP FUNCTION getrngfunc9(int);
693 DROP FUNCTION rngfunct(int);
697 CREATE TEMPORARY SEQUENCE rngfunc_rescan_seq1;
698 CREATE TEMPORARY SEQUENCE rngfunc_rescan_seq2;
699 CREATE TYPE rngfunc_rescan_t AS (i integer, s bigint);
700 CREATE FUNCTION rngfunc_sql(int,int) RETURNS setof rngfunc_rescan_t AS 'SELECT i, nextval(''rngfunc_rescan_seq1'') FROM generate_series($1,$2) i;' LANGUAGE SQL;
701 -- plpgsql functions use materialize mode
702 CREATE FUNCTION rngfunc_mat(int,int) RETURNS setof rngfunc_rescan_t AS 'begin for i in $1..$2 loop return next (i, nextval(''rngfunc_rescan_seq2'')); end loop; end;' LANGUAGE plpgsql;
703 --invokes ExecReScanFunctionScan - all these cases should materialize the function only once
704 -- LEFT JOIN on a condition that the planner can't prove to be true is used to ensure the function
705 -- is on the inner path of a nestloop join
706 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
712 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN rngfunc_sql(11,13) ON (r+i)<100;
726 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
732 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN rngfunc_sql(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100;
746 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
752 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN rngfunc_mat(11,13) ON (r+i)<100;
766 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
772 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN rngfunc_mat(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100;
786 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
792 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN ROWS FROM( rngfunc_sql(11,13), rngfunc_mat(11,13) ) WITH ORDINALITY AS f(i1,s1,i2,s2,o) ON (r+i1+i2)<100;
793 r | i1 | s1 | i2 | s2 | o
794 ---+----+----+----+----+---
795 1 | 11 | 1 | 11 | 1 | 1
796 1 | 12 | 2 | 12 | 2 | 2
797 1 | 13 | 3 | 13 | 3 | 3
798 2 | 11 | 1 | 11 | 1 | 1
799 2 | 12 | 2 | 12 | 2 | 2
800 2 | 13 | 3 | 13 | 3 | 3
801 3 | 11 | 1 | 11 | 1 | 1
802 3 | 12 | 2 | 12 | 2 | 2
803 3 | 13 | 3 | 13 | 3 | 3
806 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) f(i) ON (r+i)<100;
820 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) WITH ORDINALITY AS f(i,o) ON (r+i)<100;
834 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN unnest(array[10,20,30]) f(i) ON (r+i)<100;
848 SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN unnest(array[10,20,30]) WITH ORDINALITY AS f(i,o) ON (r+i)<100;
862 --invokes ExecReScanFunctionScan with chgParam != NULL (using implied LATERAL)
863 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
869 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_sql(10+r,13);
880 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
886 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_sql(10+r,13) WITH ORDINALITY AS f(i,s,o);
897 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
903 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_sql(11,10+r);
914 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
920 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_sql(11,10+r) WITH ORDINALITY AS f(i,s,o);
931 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
937 SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), rngfunc_sql(r1,r2);
952 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
958 SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), rngfunc_sql(r1,r2) WITH ORDINALITY AS f(i,s,o);
960 ----+----+----+----+---
970 16 | 20 | 20 | 10 | 5
973 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
979 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_mat(10+r,13);
990 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
996 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_mat(10+r,13) WITH ORDINALITY AS f(i,s,o);
1007 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1013 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_mat(11,10+r);
1024 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1030 SELECT * FROM (VALUES (1),(2),(3)) v(r), rngfunc_mat(11,10+r) WITH ORDINALITY AS f(i,s,o);
1041 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1047 SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), rngfunc_mat(r1,r2);
1062 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1068 SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), rngfunc_mat(r1,r2) WITH ORDINALITY AS f(i,s,o);
1070 ----+----+----+----+---
1071 11 | 12 | 11 | 1 | 1
1072 11 | 12 | 12 | 2 | 2
1073 13 | 15 | 13 | 3 | 1
1074 13 | 15 | 14 | 4 | 2
1075 13 | 15 | 15 | 5 | 3
1076 16 | 20 | 16 | 6 | 1
1077 16 | 20 | 17 | 7 | 2
1078 16 | 20 | 18 | 8 | 3
1079 16 | 20 | 19 | 9 | 4
1080 16 | 20 | 20 | 10 | 5
1083 -- selective rescan of multiple functions:
1084 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1090 SELECT * FROM (VALUES (1),(2),(3)) v(r), ROWS FROM( rngfunc_sql(11,11), rngfunc_mat(10+r,13) );
1092 ---+----+---+----+---
1101 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1107 SELECT * FROM (VALUES (1),(2),(3)) v(r), ROWS FROM( rngfunc_sql(10+r,13), rngfunc_mat(11,11) );
1109 ---+----+---+----+---
1118 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1124 SELECT * FROM (VALUES (1),(2),(3)) v(r), ROWS FROM( rngfunc_sql(10+r,13), rngfunc_mat(10+r,13) );
1126 ---+----+---+----+---
1135 SELECT setval('rngfunc_rescan_seq1',1,false),setval('rngfunc_rescan_seq2',1,false);
1141 SELECT * FROM generate_series(1,2) r1, generate_series(r1,3) r2, ROWS FROM( rngfunc_sql(10+r1,13), rngfunc_mat(10+r2,13) );
1142 r1 | r2 | i | s | i | s
1143 ----+----+----+----+----+---
1144 1 | 1 | 11 | 1 | 11 | 1
1145 1 | 1 | 12 | 2 | 12 | 2
1146 1 | 1 | 13 | 3 | 13 | 3
1147 1 | 2 | 11 | 4 | 12 | 4
1148 1 | 2 | 12 | 5 | 13 | 5
1150 1 | 3 | 11 | 7 | 13 | 6
1153 2 | 2 | 12 | 10 | 12 | 7
1154 2 | 2 | 13 | 11 | 13 | 8
1155 2 | 3 | 12 | 12 | 13 | 9
1159 SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) f(i);
1185 SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) WITH ORDINALITY AS f(i,o);
1211 SELECT * FROM (VALUES (1),(2),(3)) v(r), unnest(array[r*10,r*20,r*30]) f(i);
1225 SELECT * FROM (VALUES (1),(2),(3)) v(r), unnest(array[r*10,r*20,r*30]) WITH ORDINALITY AS f(i,o);
1240 SELECT * FROM (VALUES (1),(2),(3)) v1(r1),
1241 LATERAL (SELECT r1, * FROM (VALUES (10),(20),(30)) v2(r2)
1242 LEFT JOIN generate_series(21,23) f(i) ON ((r2+i)<100) OFFSET 0) s1;
1274 SELECT * FROM (VALUES (1),(2),(3)) v1(r1),
1275 LATERAL (SELECT r1, * FROM (VALUES (10),(20),(30)) v2(r2)
1276 LEFT JOIN generate_series(20+r1,23) f(i) ON ((r2+i)<100) OFFSET 0) s1;
1299 SELECT * FROM (VALUES (1),(2),(3)) v1(r1),
1300 LATERAL (SELECT r1, * FROM (VALUES (10),(20),(30)) v2(r2)
1301 LEFT JOIN generate_series(r2,r2+3) f(i) ON ((r2+i)<100) OFFSET 0) s1;
1342 SELECT * FROM (VALUES (1),(2),(3)) v1(r1),
1343 LATERAL (SELECT r1, * FROM (VALUES (10),(20),(30)) v2(r2)
1344 LEFT JOIN generate_series(r1,2+r2/5) f(i) ON ((r2+i)<100) OFFSET 0) s1;
1394 -- check handling of FULL JOIN with multiple lateral references (bug #15741)
1396 FROM (VALUES (1),(2)) v1(r1)
1399 FROM generate_series(1, v1.r1) AS gs1
1402 FROM generate_series(1, gs1) AS gs2
1403 LEFT JOIN generate_series(1, gs2) AS gs3 ON TRUE
1405 FULL JOIN generate_series(1, v1.r1) AS gs4 ON FALSE
1407 r1 | gs1 | gs2 | gs3 | gs4
1408 ----+-----+-----+-----+-----
1419 DROP FUNCTION rngfunc_sql(int,int);
1420 DROP FUNCTION rngfunc_mat(int,int);
1421 DROP SEQUENCE rngfunc_rescan_seq1;
1422 DROP SEQUENCE rngfunc_rescan_seq2;
1424 -- Test cases involving OUT parameters
1426 CREATE FUNCTION rngfunc(in f1 int, out f2 int)
1427 AS 'select $1+1' LANGUAGE sql;
1434 SELECT * FROM rngfunc(42);
1440 SELECT * FROM rngfunc(42) AS p(x);
1446 -- explicit spec of return type is OK
1447 CREATE OR REPLACE FUNCTION rngfunc(in f1 int, out f2 int) RETURNS int
1448 AS 'select $1+1' LANGUAGE sql;
1449 -- error, wrong result type
1450 CREATE OR REPLACE FUNCTION rngfunc(in f1 int, out f2 int) RETURNS float
1451 AS 'select $1+1' LANGUAGE sql;
1452 ERROR: function result type must be integer because of OUT parameters
1453 -- with multiple OUT params you must get a RECORD result
1454 CREATE OR REPLACE FUNCTION rngfunc(in f1 int, out f2 int, out f3 text) RETURNS int
1455 AS 'select $1+1' LANGUAGE sql;
1456 ERROR: function result type must be record because of OUT parameters
1457 CREATE OR REPLACE FUNCTION rngfunc(in f1 int, out f2 int, out f3 text)
1459 AS 'select $1+1' LANGUAGE sql;
1460 ERROR: cannot change return type of existing function
1461 HINT: Use DROP FUNCTION rngfunc(integer) first.
1462 CREATE OR REPLACE FUNCTION rngfuncr(in f1 int, out f2 int, out text)
1463 AS $$select $1-1, $1::text || 'z'$$ LANGUAGE sql;
1464 SELECT f1, rngfuncr(f1) FROM int4_tbl;
1466 -------------+----------------------------
1468 123456 | (123455,123456z)
1469 -123456 | (-123457,-123456z)
1470 2147483647 | (2147483646,2147483647z)
1471 -2147483647 | (-2147483648,-2147483647z)
1474 SELECT * FROM rngfuncr(42);
1480 SELECT * FROM rngfuncr(42) AS p(a,b);
1486 CREATE OR REPLACE FUNCTION rngfuncb(in f1 int, inout f2 int, out text)
1487 AS $$select $2-1, $1::text || 'z'$$ LANGUAGE sql;
1488 SELECT f1, rngfuncb(f1, f1/2) FROM int4_tbl;
1490 -------------+----------------------------
1492 123456 | (61727,123456z)
1493 -123456 | (-61729,-123456z)
1494 2147483647 | (1073741822,2147483647z)
1495 -2147483647 | (-1073741824,-2147483647z)
1498 SELECT * FROM rngfuncb(42, 99);
1504 SELECT * FROM rngfuncb(42, 99) AS p(a,b);
1510 -- Can reference function with or without OUT params for DROP, etc
1511 DROP FUNCTION rngfunc(int);
1512 DROP FUNCTION rngfuncr(in f2 int, out f1 int, out text);
1513 DROP FUNCTION rngfuncb(in f1 int, inout f2 int);
1515 -- For my next trick, polymorphic OUT parameters
1517 CREATE FUNCTION dup (f1 anyelement, f2 out anyelement, f3 out anyarray)
1518 AS 'select $1, array[$1,$1]' LANGUAGE sql;
1525 SELECT dup('xyz'); -- fails
1526 ERROR: could not determine polymorphic type because input has type unknown
1527 SELECT dup('xyz'::text);
1533 SELECT * FROM dup('xyz'::text);
1539 -- fails, as we are attempting to rename first argument
1540 CREATE OR REPLACE FUNCTION dup (inout f2 anyelement, out f3 anyarray)
1541 AS 'select $1, array[$1,$1]' LANGUAGE sql;
1542 ERROR: cannot change name of input parameter "f1"
1543 HINT: Use DROP FUNCTION dup(anyelement) first.
1544 DROP FUNCTION dup(anyelement);
1545 -- equivalent behavior, though different name exposed for input arg
1546 CREATE OR REPLACE FUNCTION dup (inout f2 anyelement, out f3 anyarray)
1547 AS 'select $1, array[$1,$1]' LANGUAGE sql;
1554 DROP FUNCTION dup(anyelement);
1555 -- fails, no way to deduce outputs
1556 CREATE FUNCTION bad (f1 int, out f2 anyelement, out f3 anyarray)
1557 AS 'select $1, array[$1,$1]' LANGUAGE sql;
1558 ERROR: cannot determine result data type
1559 DETAIL: A result of type anyelement requires at least one input of type anyelement, anyarray, anynonarray, anyenum, anyrange, or anymultirange.
1560 CREATE FUNCTION dup (f1 anycompatible, f2 anycompatiblearray, f3 out anycompatible, f4 out anycompatiblearray)
1561 AS 'select $1, $2' LANGUAGE sql;
1562 SELECT dup(22, array[44]);
1568 SELECT dup(4.5, array[44]);
1574 SELECT dup(22, array[44::bigint]);
1580 SELECT *, pg_typeof(f3), pg_typeof(f4) FROM dup(22, array[44::bigint]);
1581 f3 | f4 | pg_typeof | pg_typeof
1582 ----+------+-----------+-----------
1583 22 | {44} | bigint | bigint[]
1586 DROP FUNCTION dup(f1 anycompatible, f2 anycompatiblearray);
1587 CREATE FUNCTION dup (f1 anycompatiblerange, f2 out anycompatible, f3 out anycompatiblearray, f4 out anycompatiblerange)
1588 AS 'select lower($1), array[lower($1), upper($1)], $1' LANGUAGE sql;
1589 SELECT dup(int4range(4,7));
1591 ---------------------
1595 SELECT dup(numrange(4,7));
1597 ---------------------
1601 SELECT dup(textrange('aaa', 'bbb'));
1603 -------------------------------
1604 (aaa,"{aaa,bbb}","[aaa,bbb)")
1607 DROP FUNCTION dup(f1 anycompatiblerange);
1608 -- fails, no way to deduce outputs
1609 CREATE FUNCTION bad (f1 anyarray, out f2 anycompatible, out f3 anycompatiblearray)
1610 AS 'select $1, array[$1,$1]' LANGUAGE sql;
1611 ERROR: cannot determine result data type
1612 DETAIL: A result of type anycompatible requires at least one input of type anycompatible, anycompatiblearray, anycompatiblenonarray, anycompatiblerange, or anycompatiblemultirange.
1616 CREATE OR REPLACE FUNCTION rngfunc()
1617 RETURNS TABLE(a int)
1618 AS $$ SELECT a FROM generate_series(1,5) a(a) $$ LANGUAGE sql;
1619 SELECT * FROM rngfunc();
1629 DROP FUNCTION rngfunc();
1630 CREATE OR REPLACE FUNCTION rngfunc(int)
1631 RETURNS TABLE(a int, b int)
1633 FROM generate_series(1,$1) a(a),
1634 generate_series(1,$1) b(b) $$ LANGUAGE sql;
1635 SELECT * FROM rngfunc(3);
1649 DROP FUNCTION rngfunc(int);
1650 -- case that causes change of typmod knowledge during inlining
1651 CREATE OR REPLACE FUNCTION rngfunc()
1652 RETURNS TABLE(a varchar(5))
1653 AS $$ SELECT 'hello'::varchar(5) $$ LANGUAGE sql STABLE;
1654 SELECT * FROM rngfunc() GROUP BY 1;
1660 DROP FUNCTION rngfunc();
1662 -- some tests on SQL functions with RETURNING
1664 create temp table tt(f1 serial, data text);
1665 create function insert_tt(text) returns int as
1666 $$ insert into tt(data) values($1) returning f1 $$
1668 select insert_tt('foo');
1674 select insert_tt('bar');
1687 -- insert will execute to completion even if function needs just 1 row
1688 create or replace function insert_tt(text) returns int as
1689 $$ insert into tt(data) values($1),($1||$1) returning f1 $$
1691 select insert_tt('fool');
1706 -- setof does what's expected
1707 create or replace function insert_tt2(text,text) returns setof int as
1708 $$ insert into tt(data) values($1),($2) returning f1 $$
1710 select insert_tt2('foolish','barrish');
1717 select * from insert_tt2('baz','quux');
1737 -- limit doesn't prevent execution to completion
1738 select insert_tt2('foolish','barrish') limit 1;
1759 -- triggers will fire, too
1760 create function noticetrigger() returns trigger as $$
1762 raise notice 'noticetrigger % %', new.f1, new.data;
1764 end $$ language plpgsql;
1765 create trigger tnoticetrigger after insert on tt for each row
1766 execute procedure noticetrigger();
1767 select insert_tt2('foolme','barme') limit 1;
1768 NOTICE: noticetrigger 11 foolme
1769 NOTICE: noticetrigger 12 barme
1793 create temp table tt_log(f1 int, data text);
1794 create rule insert_tt_rule as on insert to tt do also
1795 insert into tt_log values(new.*);
1796 select insert_tt2('foollog','barlog') limit 1;
1797 NOTICE: noticetrigger 13 foollog
1798 NOTICE: noticetrigger 14 barlog
1823 -- note that nextval() gets executed a second time in the rule expansion,
1824 -- which is expected.
1825 select * from tt_log;
1832 -- test case for a whole-row-variable bug
1833 create function rngfunc1(n integer, out a text, out b text)
1834 returns setof record
1836 as $$ select 'foo ' || i, 'bar ' || i from generate_series(1,$1) i $$;
1837 set work_mem='64kB';
1838 select t.a, t, t.a from rngfunc1(10000) t limit 1;
1840 -------+-------------------+-------
1841 foo 1 | ("foo 1","bar 1") | foo 1
1845 select t.a, t, t.a from rngfunc1(10000) t limit 1;
1847 -------+-------------------+-------
1848 foo 1 | ("foo 1","bar 1") | foo 1
1851 drop function rngfunc1(n integer);
1852 -- test use of SQL functions returning record
1853 -- this is supported in some cases where the query doesn't specify
1854 -- the actual record type ...
1855 create function array_to_set(anyarray) returns setof record as $$
1856 select i AS "index", $1[i] AS "value" from generate_subscripts($1, 1) i
1857 $$ language sql strict immutable;
1858 select array_to_set(array['one', 'two']);
1865 select * from array_to_set(array['one', 'two']) as t(f1 int,f2 text);
1872 select * from array_to_set(array['one', 'two']); -- fail
1873 ERROR: a column definition list is required for functions returning "record"
1874 LINE 1: select * from array_to_set(array['one', 'two']);
1876 -- after-the-fact coercion of the columns is now possible, too
1877 select * from array_to_set(array['one', 'two']) as t(f1 numeric(4,2),f2 text);
1884 -- and if it doesn't work, you get a compile-time not run-time error
1885 select * from array_to_set(array['one', 'two']) as t(f1 point,f2 text);
1886 ERROR: return type mismatch in function declared to return record
1887 DETAIL: Final statement returns integer instead of point at column 1.
1888 CONTEXT: SQL function "array_to_set" during startup
1889 -- with "strict", this function can't be inlined in FROM
1890 explain (verbose, costs off)
1891 select * from array_to_set(array['one', 'two']) as t(f1 numeric(4,2),f2 text);
1893 ----------------------------------------------------
1894 Function Scan on public.array_to_set t
1896 Function Call: array_to_set('{one,two}'::text[])
1899 -- but without, it can be:
1900 create or replace function array_to_set(anyarray) returns setof record as $$
1901 select i AS "index", $1[i] AS "value" from generate_subscripts($1, 1) i
1902 $$ language sql immutable;
1903 select array_to_set(array['one', 'two']);
1910 select * from array_to_set(array['one', 'two']) as t(f1 int,f2 text);
1917 select * from array_to_set(array['one', 'two']) as t(f1 numeric(4,2),f2 text);
1924 select * from array_to_set(array['one', 'two']) as t(f1 point,f2 text);
1925 ERROR: return type mismatch in function declared to return record
1926 DETAIL: Final statement returns integer instead of point at column 1.
1927 CONTEXT: SQL function "array_to_set" during inlining
1928 explain (verbose, costs off)
1929 select * from array_to_set(array['one', 'two']) as t(f1 numeric(4,2),f2 text);
1931 --------------------------------------------------------------
1932 Function Scan on pg_catalog.generate_subscripts i
1933 Output: i.i, ('{one,two}'::text[])[i.i]
1934 Function Call: generate_subscripts('{one,two}'::text[], 1)
1937 create temp table rngfunc(f1 int8, f2 int8);
1938 create function testrngfunc() returns record as $$
1939 insert into rngfunc values (1,2) returning *;
1941 select testrngfunc();
1947 select * from testrngfunc() as t(f1 int8,f2 int8);
1953 select * from testrngfunc(); -- fail
1954 ERROR: a column definition list is required for functions returning "record"
1955 LINE 1: select * from testrngfunc();
1957 drop function testrngfunc();
1958 create function testrngfunc() returns setof record as $$
1959 insert into rngfunc values (1,2), (3,4) returning *;
1961 select testrngfunc();
1968 select * from testrngfunc() as t(f1 int8,f2 int8);
1975 select * from testrngfunc(); -- fail
1976 ERROR: a column definition list is required for functions returning "record"
1977 LINE 1: select * from testrngfunc();
1979 drop function testrngfunc();
1980 -- Check that typmod imposed by a composite type is honored
1981 create type rngfunc_type as (f1 numeric(35,6), f2 numeric(35,2));
1982 create function testrngfunc() returns rngfunc_type as $$
1983 select 7.136178319899999964, 7.136178319899999964;
1984 $$ language sql immutable;
1985 explain (verbose, costs off)
1986 select testrngfunc();
1988 -------------------------------------------
1990 Output: '(7.136178,7.14)'::rngfunc_type
1993 select testrngfunc();
1999 explain (verbose, costs off)
2000 select * from testrngfunc();
2002 --------------------------------------------------
2003 Function Scan on testrngfunc
2005 Function Call: '(7.136178,7.14)'::rngfunc_type
2008 select * from testrngfunc();
2014 create or replace function testrngfunc() returns rngfunc_type as $$
2015 select 7.136178319899999964, 7.136178319899999964;
2016 $$ language sql volatile;
2017 explain (verbose, costs off)
2018 select testrngfunc();
2020 -------------------------
2022 Output: testrngfunc()
2025 select testrngfunc();
2031 explain (verbose, costs off)
2032 select * from testrngfunc();
2034 -------------------------------------
2035 Function Scan on public.testrngfunc
2037 Function Call: testrngfunc()
2040 select * from testrngfunc();
2046 drop function testrngfunc();
2047 create function testrngfunc() returns setof rngfunc_type as $$
2048 select 7.136178319899999964, 7.136178319899999964;
2049 $$ language sql immutable;
2050 explain (verbose, costs off)
2051 select testrngfunc();
2053 -------------------------
2055 Output: testrngfunc()
2059 select testrngfunc();
2065 explain (verbose, costs off)
2066 select * from testrngfunc();
2068 --------------------------------------------------------
2070 Output: 7.136178::numeric(35,6), 7.14::numeric(35,2)
2073 select * from testrngfunc();
2079 create or replace function testrngfunc() returns setof rngfunc_type as $$
2080 select 7.136178319899999964, 7.136178319899999964;
2081 $$ language sql volatile;
2082 explain (verbose, costs off)
2083 select testrngfunc();
2085 -------------------------
2087 Output: testrngfunc()
2091 select testrngfunc();
2097 explain (verbose, costs off)
2098 select * from testrngfunc();
2100 -------------------------------------
2101 Function Scan on public.testrngfunc
2103 Function Call: testrngfunc()
2106 select * from testrngfunc();
2112 create or replace function testrngfunc() returns setof rngfunc_type as $$
2113 select 1, 2 union select 3, 4 order by 1;
2114 $$ language sql immutable;
2115 explain (verbose, costs off)
2116 select testrngfunc();
2118 -------------------------
2120 Output: testrngfunc()
2124 select testrngfunc();
2131 explain (verbose, costs off)
2132 select * from testrngfunc();
2134 ----------------------------------------------------------
2135 Subquery Scan on "*SELECT*"
2136 Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1"
2149 select * from testrngfunc();
2156 -- Check a couple of error cases while we're here
2157 select * from testrngfunc() as t(f1 int8,f2 int8); -- fail, composite result
2158 ERROR: a column definition list is redundant for a function returning a named composite type
2159 LINE 1: select * from testrngfunc() as t(f1 int8,f2 int8);
2161 select * from pg_get_keywords() as t(f1 int8,f2 int8); -- fail, OUT params
2162 ERROR: a column definition list is redundant for a function with OUT parameters
2163 LINE 1: select * from pg_get_keywords() as t(f1 int8,f2 int8);
2165 select * from sin(3) as t(f1 int8,f2 int8); -- fail, scalar result type
2166 ERROR: a column definition list is only allowed for functions returning "record"
2167 LINE 1: select * from sin(3) as t(f1 int8,f2 int8);
2169 drop type rngfunc_type cascade;
2170 NOTICE: drop cascades to function testrngfunc()
2172 -- Check some cases involving added/dropped columns in a rowtype result
2174 create temp table users (userid text, seq int, email text, todrop bool, moredrop int, enabled bool);
2175 insert into users values ('id',1,'email',true,11,true);
2176 insert into users values ('id2',2,'email2',true,12,true);
2177 alter table users drop column todrop;
2178 create or replace function get_first_user() returns users as
2179 $$ SELECT * FROM users ORDER BY userid LIMIT 1; $$
2180 language sql stable;
2181 SELECT get_first_user();
2187 SELECT * FROM get_first_user();
2188 userid | seq | email | moredrop | enabled
2189 --------+-----+-------+----------+---------
2190 id | 1 | email | 11 | t
2193 create or replace function get_users() returns setof users as
2194 $$ SELECT * FROM users ORDER BY userid; $$
2195 language sql stable;
2198 ---------------------
2203 SELECT * FROM get_users();
2204 userid | seq | email | moredrop | enabled
2205 --------+-----+--------+----------+---------
2206 id | 1 | email | 11 | t
2207 id2 | 2 | email2 | 12 | t
2210 SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes
2211 userid | seq | email | moredrop | enabled | ordinality
2212 --------+-----+--------+----------+---------+------------
2213 id | 1 | email | 11 | t | 1
2214 id2 | 2 | email2 | 12 | t | 2
2217 -- multiple functions vs. dropped columns
2218 SELECT * FROM ROWS FROM(generate_series(10,11), get_users()) WITH ORDINALITY;
2219 generate_series | userid | seq | email | moredrop | enabled | ordinality
2220 -----------------+--------+-----+--------+----------+---------+------------
2221 10 | id | 1 | email | 11 | t | 1
2222 11 | id2 | 2 | email2 | 12 | t | 2
2225 SELECT * FROM ROWS FROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
2226 userid | seq | email | moredrop | enabled | generate_series | ordinality
2227 --------+-----+--------+----------+---------+-----------------+------------
2228 id | 1 | email | 11 | t | 10 | 1
2229 id2 | 2 | email2 | 12 | t | 11 | 2
2232 -- check that we can cope with post-parsing changes in rowtypes
2233 create temp view usersview as
2234 SELECT * FROM ROWS FROM(get_users(), generate_series(10,11)) WITH ORDINALITY;
2235 select * from usersview;
2236 userid | seq | email | moredrop | enabled | generate_series | ordinality
2237 --------+-----+--------+----------+---------+-----------------+------------
2238 id | 1 | email | 11 | t | 10 | 1
2239 id2 | 2 | email2 | 12 | t | 11 | 2
2242 alter table users add column junk text;
2243 select * from usersview;
2244 userid | seq | email | moredrop | enabled | generate_series | ordinality
2245 --------+-----+--------+----------+---------+-----------------+------------
2246 id | 1 | email | 11 | t | 10 | 1
2247 id2 | 2 | email2 | 12 | t | 11 | 2
2250 alter table users drop column moredrop; -- fail, view has reference
2251 ERROR: cannot drop column moredrop of table users because other objects depend on it
2252 DETAIL: view usersview depends on column moredrop of table users
2253 HINT: Use DROP ... CASCADE to drop the dependent objects too.
2254 -- We used to have a bug that would allow the above to succeed, posing
2255 -- hazards for later execution of the view. Check that the internal
2256 -- defenses for those hazards haven't bit-rotted, in case some other
2257 -- bug with similar symptoms emerges.
2259 -- destroy the dependency entry that prevents the DROP:
2260 delete from pg_depend where
2261 objid = (select oid from pg_rewrite
2262 where ev_class = 'usersview'::regclass and rulename = '_RETURN')
2264 returning pg_describe_object(classid, objid, objsubid) as obj,
2265 pg_describe_object(refclassid, refobjid, refobjsubid) as ref,
2268 --------------------------------+--------------------------------+---------
2269 rule _RETURN on view usersview | column moredrop of table users | n
2272 alter table users drop column moredrop;
2273 select * from usersview; -- expect clean failure
2274 ERROR: attribute 5 of type record has been dropped
2276 alter table users alter column seq type numeric; -- fail, view has reference
2277 ERROR: cannot alter type of a column used by a view or rule
2278 DETAIL: rule _RETURN on view usersview depends on column "seq"
2279 -- likewise, check we don't crash if the dependency goes wrong
2281 -- destroy the dependency entry that prevents the ALTER:
2282 delete from pg_depend where
2283 objid = (select oid from pg_rewrite
2284 where ev_class = 'usersview'::regclass and rulename = '_RETURN')
2286 returning pg_describe_object(classid, objid, objsubid) as obj,
2287 pg_describe_object(refclassid, refobjid, refobjsubid) as ref,
2290 --------------------------------+---------------------------+---------
2291 rule _RETURN on view usersview | column seq of table users | n
2294 alter table users alter column seq type numeric;
2295 select * from usersview; -- expect clean failure
2296 ERROR: attribute 2 of type record has wrong type
2297 DETAIL: Table has type numeric, but query expects integer.
2299 drop view usersview;
2300 drop function get_first_user();
2301 drop function get_users();
2303 -- check behavior with type coercion required for a set-op
2304 create or replace function rngfuncbar() returns setof text as
2305 $$ select 'foo'::varchar union all select 'bar'::varchar ; $$
2306 language sql stable;
2307 select rngfuncbar();
2314 select * from rngfuncbar();
2321 -- this function is now inlinable, too:
2322 explain (verbose, costs off) select * from rngfuncbar();
2324 ------------------------------------------------
2326 Output: ('foo'::character varying)
2329 Output: 'foo'::character varying
2331 Output: 'bar'::character varying
2334 drop function rngfuncbar();
2335 -- check handling of a SQL function with multiple OUT params (bug #5777)
2336 create or replace function rngfuncbar(out integer, out numeric) as
2337 $$ select (1, 2.1) $$ language sql;
2338 select * from rngfuncbar();
2344 create or replace function rngfuncbar(out integer, out numeric) as
2345 $$ select (1, 2) $$ language sql;
2346 select * from rngfuncbar(); -- fail
2347 ERROR: function return row and query-specified return row do not match
2348 DETAIL: Returned type integer at ordinal position 2, but query expects numeric.
2349 create or replace function rngfuncbar(out integer, out numeric) as
2350 $$ select (1, 2.1, 3) $$ language sql;
2351 select * from rngfuncbar(); -- fail
2352 ERROR: function return row and query-specified return row do not match
2353 DETAIL: Returned row contains 3 attributes, but query expects 2.
2354 drop function rngfuncbar();
2355 -- check whole-row-Var handling in nested lateral functions (bug #11703)
2356 create function extractq2(t int8_tbl) returns int8 as $$
2358 $$ language sql immutable;
2359 explain (verbose, costs off)
2360 select x from int8_tbl, extractq2(int8_tbl) f(x);
2362 ------------------------------------------
2365 -> Seq Scan on public.int8_tbl
2366 Output: int8_tbl.q1, int8_tbl.q2
2367 -> Function Scan on f
2369 Function Call: int8_tbl.q2
2372 select x from int8_tbl, extractq2(int8_tbl) f(x);
2382 create function extractq2_2(t int8_tbl) returns table(ret1 int8) as $$
2383 select extractq2(t) offset 0
2384 $$ language sql immutable;
2385 explain (verbose, costs off)
2386 select x from int8_tbl, extractq2_2(int8_tbl) f(x);
2388 -----------------------------------
2390 Output: ((int8_tbl.*).q2)
2391 -> Seq Scan on public.int8_tbl
2394 Output: (int8_tbl.*).q2
2397 select x from int8_tbl, extractq2_2(int8_tbl) f(x);
2407 -- without the "offset 0", this function gets optimized quite differently
2408 create function extractq2_2_opt(t int8_tbl) returns table(ret1 int8) as $$
2410 $$ language sql immutable;
2411 explain (verbose, costs off)
2412 select x from int8_tbl, extractq2_2_opt(int8_tbl) f(x);
2414 -----------------------------
2415 Seq Scan on public.int8_tbl
2419 select x from int8_tbl, extractq2_2_opt(int8_tbl) f(x);
2429 -- check handling of nulls in SRF results (bug #7808)
2430 create type rngfunc2 as (a integer, b text);
2431 select *, row_to_json(u) from unnest(array[(1,'foo')::rngfunc2, null::rngfunc2]) u;
2433 ---+-----+---------------------
2434 1 | foo | {"a":1,"b":"foo"}
2435 | | {"a":null,"b":null}
2438 select *, row_to_json(u) from unnest(array[null::rngfunc2, null::rngfunc2]) u;
2440 ---+---+---------------------
2441 | | {"a":null,"b":null}
2442 | | {"a":null,"b":null}
2445 select *, row_to_json(u) from unnest(array[null::rngfunc2, (1,'foo')::rngfunc2, null::rngfunc2]) u;
2447 ---+-----+---------------------
2448 | | {"a":null,"b":null}
2449 1 | foo | {"a":1,"b":"foo"}
2450 | | {"a":null,"b":null}
2453 select *, row_to_json(u) from unnest(array[]::rngfunc2[]) u;
2455 ---+---+-------------
2459 -- check handling of functions pulled up into function RTEs (bug #17227)
2460 explain (verbose, costs off)
2462 (select jsonb_path_query_array(module->'lectures', '$[*]') as lecture
2463 from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb])
2464 as unnested_modules(module)) as ss,
2465 jsonb_to_recordset(ss.lecture) as j (id text);
2467 --------------------------------------------------------------------------------------------------------------------------------------------------------
2469 Output: jsonb_path_query_array((unnested_modules.module -> 'lectures'::text), '$[*]'::jsonpath, '{}'::jsonb, false), j.id
2470 -> Function Scan on pg_catalog.unnest unnested_modules
2471 Output: unnested_modules.module
2472 Function Call: unnest('{"{\"lectures\": [{\"id\": \"1\"}]}"}'::jsonb[])
2473 -> Function Scan on pg_catalog.jsonb_to_recordset j
2475 Function Call: jsonb_to_recordset(jsonb_path_query_array((unnested_modules.module -> 'lectures'::text), '$[*]'::jsonpath, '{}'::jsonb, false))
2479 (select jsonb_path_query_array(module->'lectures', '$[*]') as lecture
2480 from unnest(array['{"lectures": [{"id": "1"}]}'::jsonb])
2481 as unnested_modules(module)) as ss,
2482 jsonb_to_recordset(ss.lecture) as j (id text);
2484 ---------------+----
2488 -- check detection of mismatching record types with a const-folded expression
2489 with a(b) as (values (row(1,2,3)))
2490 select * from a, coalesce(b) as c(d int, e int); -- fail
2491 ERROR: function return row and query-specified return row do not match
2492 DETAIL: Returned row contains 3 attributes, but query expects 2.
2493 with a(b) as (values (row(1,2,3)))
2494 select * from a, coalesce(b) as c(d int, e int, f int, g int); -- fail
2495 ERROR: function return row and query-specified return row do not match
2496 DETAIL: Returned row contains 3 attributes, but query expects 4.
2497 with a(b) as (values (row(1,2,3)))
2498 select * from a, coalesce(b) as c(d int, e int, f float); -- fail
2499 ERROR: function return row and query-specified return row do not match
2500 DETAIL: Returned type integer at ordinal position 3, but query expects double precision.
2501 select * from int8_tbl, coalesce(row(1)) as (a int, b int); -- fail
2502 ERROR: function return row and query-specified return row do not match
2503 DETAIL: Returned row contains 1 attribute, but query expects 2.