diff options
Diffstat (limited to 'src/test')
| -rw-r--r-- | src/test/regress/expected/rangefuncs.out | 772 | ||||
| -rw-r--r-- | src/test/regress/sql/rangefuncs.sql | 271 |
2 files changed, 763 insertions, 280 deletions
diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 37391dcfce7..418f92c4dbe 100644 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -67,6 +67,15 @@ select * from unnest(array[1.0::float8]) with ordinality as z(a,ord); 1 | 1 (1 row) +select row_to_json(s.*) from generate_series(11,14) with ordinality s; + row_to_json +------------------------- + {"s":11,"ordinality":1} + {"s":12,"ordinality":2} + {"s":13,"ordinality":3} + {"s":14,"ordinality":4} +(4 rows) + -- ordinality vs. views create temporary view vw_ord as select * from (values (1)) v(n) join foot(1) with ordinality as z(a,b,ord) on (n=ord); select * from vw_ord; @@ -87,59 +96,207 @@ select definition from pg_views where viewname='vw_ord'; (1 row) drop view vw_ord; --- ordinality vs. rewind and reverse scan +-- multiple functions +select * from table(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord); + a | b | c | d | ord +---+-----+---+----+----- + 1 | 11 | 2 | 22 | 1 + 1 | 111 | | | 2 +(2 rows) + +create temporary view vw_ord as select * from (values (1)) v(n) join table(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord) on (n=ord); +select * from vw_ord; + n | a | b | c | d | ord +---+---+----+---+----+----- + 1 | 1 | 11 | 2 | 22 | 1 +(1 row) + +select definition from pg_views where viewname='vw_ord'; + definition +----------------------------------------------------------------------------------------- + SELECT v.n, + + z.a, + + z.b, + + z.c, + + z.d, + + z.ord + + FROM (( VALUES (1)) v(n) + + JOIN TABLE(foot(1), foot(2)) WITH ORDINALITY z(a, b, c, d, ord) ON ((v.n = z.ord))); +(1 row) + +drop view vw_ord; +-- expansions of unnest() +select * from unnest(array[10,20],array['foo','bar'],array[1.0]); + unnest | unnest | unnest +--------+--------+-------- + 10 | foo | 1.0 + 20 | bar | +(2 rows) + +select * from unnest(array[10,20],array['foo','bar'],array[1.0]) with ordinality as z(a,b,c,ord); + a | b | c | ord +----+-----+-----+----- + 10 | foo | 1.0 | 1 + 20 | bar | | 2 +(2 rows) + +select * from table(unnest(array[10,20],array['foo','bar'],array[1.0])) with ordinality as z(a,b,c,ord); + a | b | c | ord +----+-----+-----+----- + 10 | foo | 1.0 | 1 + 20 | bar | | 2 +(2 rows) + +select * from table(unnest(array[10,20],array['foo','bar']), generate_series(101,102)) with ordinality as z(a,b,c,ord); + a | b | c | ord +----+-----+-----+----- + 10 | foo | 101 | 1 + 20 | bar | 102 | 2 +(2 rows) + +create temporary view vw_ord as select * from unnest(array[10,20],array['foo','bar'],array[1.0]) as z(a,b,c); +select * from vw_ord; + a | b | c +----+-----+----- + 10 | foo | 1.0 + 20 | bar | +(2 rows) + +select definition from pg_views where viewname='vw_ord'; + definition +---------------------------------------------------------------------------------------- + SELECT z.a, + + z.b, + + z.c + + FROM UNNEST(ARRAY[10, 20], ARRAY['foo'::text, 'bar'::text], ARRAY[1.0]) z(a, b, c); +(1 row) + +drop view vw_ord; +create temporary view vw_ord as select * from table(unnest(array[10,20],array['foo','bar'],array[1.0])) as z(a,b,c); +select * from vw_ord; + a | b | c +----+-----+----- + 10 | foo | 1.0 + 20 | bar | +(2 rows) + +select definition from pg_views where viewname='vw_ord'; + definition +---------------------------------------------------------------------------------------- + SELECT z.a, + + z.b, + + z.c + + FROM UNNEST(ARRAY[10, 20], ARRAY['foo'::text, 'bar'::text], ARRAY[1.0]) z(a, b, c); +(1 row) + +drop view vw_ord; +create temporary view vw_ord as select * from table(unnest(array[10,20],array['foo','bar']), generate_series(1,2)) as z(a,b,c); +select * from vw_ord; + a | b | c +----+-----+--- + 10 | foo | 1 + 20 | bar | 2 +(2 rows) + +select definition from pg_views where viewname='vw_ord'; + definition +------------------------------------------------------------------------------------------------------------------ + SELECT z.a, + + z.b, + + z.c + + FROM TABLE(unnest(ARRAY[10, 20]), unnest(ARRAY['foo'::text, 'bar'::text]), generate_series(1, 2)) z(a, b, c); +(1 row) + +drop view vw_ord; +-- ordinality and multiple functions vs. rewind and reverse scan begin; -declare foo scroll cursor for select * from generate_series(1,5) with ordinality as g(i,o); +declare foo scroll cursor for select * from table(generate_series(1,5),generate_series(1,2)) with ordinality as g(i,j,o); fetch all from foo; - i | o ----+--- - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 + i | j | o +---+---+--- + 1 | 1 | 1 + 2 | 2 | 2 + 3 | | 3 + 4 | | 4 + 5 | | 5 (5 rows) fetch backward all from foo; - i | o ----+--- - 5 | 5 - 4 | 4 - 3 | 3 - 2 | 2 - 1 | 1 + i | j | o +---+---+--- + 5 | | 5 + 4 | | 4 + 3 | | 3 + 2 | 2 | 2 + 1 | 1 | 1 (5 rows) fetch all from foo; - i | o ----+--- - 1 | 1 - 2 | 2 - 3 | 3 - 4 | 4 - 5 | 5 + i | j | o +---+---+--- + 1 | 1 | 1 + 2 | 2 | 2 + 3 | | 3 + 4 | | 4 + 5 | | 5 (5 rows) fetch next from foo; - i | o ----+--- + i | j | o +---+---+--- (0 rows) fetch next from foo; - i | o ----+--- + i | j | o +---+---+--- (0 rows) fetch prior from foo; - i | o ----+--- - 5 | 5 + i | j | o +---+---+--- + 5 | | 5 (1 row) fetch absolute 1 from foo; - i | o ----+--- - 1 | 1 + i | j | o +---+---+--- + 1 | 1 | 1 +(1 row) + +fetch next from foo; + i | j | o +---+---+--- + 2 | 2 | 2 +(1 row) + +fetch next from foo; + i | j | o +---+---+--- + 3 | | 3 +(1 row) + +fetch next from foo; + i | j | o +---+---+--- + 4 | | 4 +(1 row) + +fetch prior from foo; + i | j | o +---+---+--- + 3 | | 3 +(1 row) + +fetch prior from foo; + i | j | o +---+---+--- + 2 | 2 | 2 +(1 row) + +fetch prior from foo; + i | j | o +---+---+--- + 1 | 1 | 1 (1 row) commit; @@ -199,62 +356,61 @@ INSERT INTO foo VALUES(1,1,'Joe'); INSERT INTO foo VALUES(1,2,'Ed'); INSERT INTO foo VALUES(2,1,'Mary'); -- sql, proretset = f, prorettype = b -CREATE FUNCTION getfoo(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; +CREATE FUNCTION getfoo1(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL; +SELECT * FROM getfoo1(1) AS t1; t1 ---- 1 (1 row) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +SELECT * FROM getfoo1(1) WITH ORDINALITY AS t1(v,o); v | o ---+--- 1 | 1 (1 row) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo1(1); SELECT * FROM vw_getfoo; - getfoo --------- - 1 + getfoo1 +--------- + 1 (1 row) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY as t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo1(1) WITH ORDINALITY as t1(v,o); SELECT * FROM vw_getfoo; v | o ---+--- 1 | 1 (1 row) --- sql, proretset = t, prorettype = b DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; +-- sql, proretset = t, prorettype = b +CREATE FUNCTION getfoo2(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo2(1) AS t1; t1 ---- 1 1 (2 rows) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +SELECT * FROM getfoo2(1) WITH ORDINALITY AS t1(v,o); v | o ---+--- 1 | 1 1 | 2 (2 rows) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo2(1); SELECT * FROM vw_getfoo; - getfoo --------- - 1 - 1 + getfoo2 +--------- + 1 + 1 (2 rows) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo2(1) WITH ORDINALITY AS t1(v,o); SELECT * FROM vw_getfoo; v | o ---+--- @@ -262,34 +418,33 @@ SELECT * FROM vw_getfoo; 1 | 2 (2 rows) --- sql, proretset = t, prorettype = b DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; +-- sql, proretset = t, prorettype = b +CREATE FUNCTION getfoo3(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo3(1) AS t1; t1 ----- Joe Ed (2 rows) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +SELECT * FROM getfoo3(1) WITH ORDINALITY AS t1(v,o); v | o -----+--- Joe | 1 Ed | 2 (2 rows) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo3(1); SELECT * FROM vw_getfoo; - getfoo --------- + getfoo3 +--------- Joe Ed (2 rows) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo3(1) WITH ORDINALITY AS t1(v,o); SELECT * FROM vw_getfoo; v | o -----+--- @@ -297,23 +452,22 @@ SELECT * FROM vw_getfoo; Ed | 2 (2 rows) --- sql, proretset = f, prorettype = c DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; +-- sql, proretset = f, prorettype = c +CREATE FUNCTION getfoo4(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo4(1) AS t1; fooid | foosubid | fooname -------+----------+--------- 1 | 1 | Joe (1 row) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +SELECT * FROM getfoo4(1) WITH ORDINALITY AS t1(a,b,c,o); a | b | c | o ---+---+-----+--- 1 | 1 | Joe | 1 (1 row) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo4(1); SELECT * FROM vw_getfoo; fooid | foosubid | fooname -------+----------+--------- @@ -321,32 +475,31 @@ SELECT * FROM vw_getfoo; (1 row) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo4(1) WITH ORDINALITY AS t1(a,b,c,o); SELECT * FROM vw_getfoo; a | b | c | o ---+---+-----+--- 1 | 1 | Joe | 1 (1 row) --- sql, proretset = t, prorettype = c DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; +-- sql, proretset = t, prorettype = c +CREATE FUNCTION getfoo5(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo5(1) AS t1; fooid | foosubid | fooname -------+----------+--------- 1 | 1 | Joe 1 | 2 | Ed (2 rows) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +SELECT * FROM getfoo5(1) WITH ORDINALITY AS t1(a,b,c,o); a | b | c | o ---+---+-----+--- 1 | 1 | Joe | 1 1 | 2 | Ed | 2 (2 rows) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo5(1); SELECT * FROM vw_getfoo; fooid | foosubid | fooname -------+----------+--------- @@ -355,7 +508,7 @@ SELECT * FROM vw_getfoo; (2 rows) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo5(1) WITH ORDINALITY AS t1(a,b,c,o); SELECT * FROM vw_getfoo; a | b | c | o ---+---+-----+--- @@ -363,18 +516,22 @@ SELECT * FROM vw_getfoo; 1 | 2 | Ed | 2 (2 rows) --- ordinality not supported for returns record yet --- sql, proretset = f, prorettype = record DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text); +-- sql, proretset = f, prorettype = record +CREATE FUNCTION getfoo6(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo6(1) AS t1(fooid int, foosubid int, fooname text); fooid | foosubid | fooname -------+----------+--------- 1 | 1 | Joe (1 row) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS +SELECT * FROM TABLE( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY; + fooid | foosubid | fooname | ordinality +-------+----------+---------+------------ + 1 | 1 | Joe | 1 +(1 row) + +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo6(1) AS (fooid int, foosubid int, fooname text); SELECT * FROM vw_getfoo; fooid | foosubid | fooname @@ -382,18 +539,34 @@ SELECT * FROM vw_getfoo; 1 | 1 | Joe (1 row) --- sql, proretset = t, prorettype = record DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text); +CREATE VIEW vw_getfoo AS + SELECT * FROM TABLE( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) + WITH ORDINALITY; +SELECT * FROM vw_getfoo; + fooid | foosubid | fooname | ordinality +-------+----------+---------+------------ + 1 | 1 | Joe | 1 +(1 row) + +DROP VIEW vw_getfoo; +-- sql, proretset = t, prorettype = record +CREATE FUNCTION getfoo7(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo7(1) AS t1(fooid int, foosubid int, fooname text); fooid | foosubid | fooname -------+----------+--------- 1 | 1 | Joe 1 | 2 | Ed (2 rows) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS +SELECT * FROM TABLE( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY; + fooid | foosubid | fooname | ordinality +-------+----------+---------+------------ + 1 | 1 | Joe | 1 + 1 | 2 | Ed | 2 +(2 rows) + +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo7(1) AS (fooid int, foosubid int, fooname text); SELECT * FROM vw_getfoo; fooid | foosubid | fooname @@ -402,54 +575,63 @@ SELECT * FROM vw_getfoo; 1 | 2 | Ed (2 rows) --- plpgsql, proretset = f, prorettype = b DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE plpgsql; -SELECT * FROM getfoo(1) AS t1; +CREATE VIEW vw_getfoo AS + SELECT * FROM TABLE( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) + WITH ORDINALITY; +SELECT * FROM vw_getfoo; + fooid | foosubid | fooname | ordinality +-------+----------+---------+------------ + 1 | 1 | Joe | 1 + 1 | 2 | Ed | 2 +(2 rows) + +DROP VIEW vw_getfoo; +-- plpgsql, proretset = f, prorettype = b +CREATE FUNCTION getfoo8(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE plpgsql; +SELECT * FROM getfoo8(1) AS t1; t1 ---- 1 (1 row) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +SELECT * FROM getfoo8(1) WITH ORDINALITY AS t1(v,o); v | o ---+--- 1 | 1 (1 row) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo8(1); SELECT * FROM vw_getfoo; - getfoo --------- - 1 + getfoo8 +--------- + 1 (1 row) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo8(1) WITH ORDINALITY AS t1(v,o); SELECT * FROM vw_getfoo; v | o ---+--- 1 | 1 (1 row) --- plpgsql, proretset = f, prorettype = c DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE plpgsql; -SELECT * FROM getfoo(1) AS t1; +-- plpgsql, proretset = f, prorettype = c +CREATE FUNCTION getfoo9(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE plpgsql; +SELECT * FROM getfoo9(1) AS t1; fooid | foosubid | fooname -------+----------+--------- 1 | 1 | Joe (1 row) -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +SELECT * FROM getfoo9(1) WITH ORDINALITY AS t1(a,b,c,o); a | b | c | o ---+---+-----+--- 1 | 1 | Joe | 1 (1 row) -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo9(1); SELECT * FROM vw_getfoo; fooid | foosubid | fooname -------+----------+--------- @@ -457,7 +639,7 @@ SELECT * FROM vw_getfoo; (1 row) DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo9(1) WITH ORDINALITY AS t1(a,b,c,o); SELECT * FROM vw_getfoo; a | b | c | o ---+---+-----+--- @@ -465,23 +647,82 @@ SELECT * FROM vw_getfoo; (1 row) DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); +-- mix 'n match kinds, to exercise expandRTE and related logic +select * from table(getfoo1(1),getfoo2(1),getfoo3(1),getfoo4(1),getfoo5(1), + getfoo6(1) AS (fooid int, foosubid int, fooname text), + getfoo7(1) AS (fooid int, foosubid int, fooname text), + getfoo8(1),getfoo9(1)) + with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u); + a | b | c | d | e | f | g | h | i | j | k | l | m | o | p | q | r | s | t | u +---+---+-----+---+---+-----+---+---+-----+---+---+-----+---+---+-----+---+---+---+-----+--- + 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | 1 | Joe | 1 + | 1 | Ed | | | | 1 | 2 | Ed | | | | 1 | 2 | Ed | | | | | 2 +(2 rows) + +select * from table(getfoo9(1),getfoo8(1), + getfoo7(1) AS (fooid int, foosubid int, fooname text), + getfoo6(1) AS (fooid int, foosubid int, fooname text), + getfoo5(1),getfoo4(1),getfoo3(1),getfoo2(1),getfoo1(1)) + with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u); + a | b | c | d | e | f | g | h | i | j | k | l | m | o | p | q | r | s | t | u +---+---+-----+---+---+---+-----+---+---+-----+---+---+-----+---+---+-----+-----+---+---+--- + 1 | 1 | Joe | 1 | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 | Joe | Joe | 1 | 1 | 1 + | | | | 1 | 2 | Ed | | | | 1 | 2 | Ed | | | | Ed | 1 | | 2 +(2 rows) + +create temporary view vw_foo as + select * from table(getfoo9(1), + getfoo7(1) AS (fooid int, foosubid int, fooname text), + getfoo1(1)) + with ordinality as t1(a,b,c,d,e,f,g,n); +select * from vw_foo; + a | b | c | d | e | f | g | n +---+---+-----+---+---+-----+---+--- + 1 | 1 | Joe | 1 | 1 | Joe | 1 | 1 + | | | 1 | 2 | Ed | | 2 +(2 rows) + +select pg_get_viewdef('vw_foo'); + pg_get_viewdef +-------------------------------------------------------------------------------------------------------------------------------------------------- + SELECT t1.a, + + t1.b, + + t1.c, + + t1.d, + + t1.e, + + t1.f, + + t1.g, + + t1.n + + FROM TABLE(getfoo9(1), getfoo7(1) AS (fooid integer, foosubid integer, fooname text), getfoo1(1)) WITH ORDINALITY t1(a, b, c, d, e, f, g, n); +(1 row) + +drop view vw_foo; +DROP FUNCTION getfoo1(int); +DROP FUNCTION getfoo2(int); +DROP FUNCTION getfoo3(int); +DROP FUNCTION getfoo4(int); +DROP FUNCTION getfoo5(int); +DROP FUNCTION getfoo6(int); +DROP FUNCTION getfoo7(int); +DROP FUNCTION getfoo8(int); +DROP FUNCTION getfoo9(int); DROP FUNCTION foot(int); DROP TABLE foo2; DROP TABLE foo; -- Rescan tests -- -CREATE TEMPORARY SEQUENCE foo_rescan_seq; +CREATE TEMPORARY SEQUENCE foo_rescan_seq1; +CREATE TEMPORARY SEQUENCE foo_rescan_seq2; CREATE TYPE foo_rescan_t AS (i integer, s bigint); -CREATE FUNCTION foo_sql(int,int) RETURNS setof foo_rescan_t AS 'SELECT i, nextval(''foo_rescan_seq'') FROM generate_series($1,$2) i;' LANGUAGE SQL; +CREATE FUNCTION foo_sql(int,int) RETURNS setof foo_rescan_t AS 'SELECT i, nextval(''foo_rescan_seq1'') FROM generate_series($1,$2) i;' LANGUAGE SQL; -- plpgsql functions use materialize mode -CREATE FUNCTION foo_mat(int,int) RETURNS setof foo_rescan_t AS 'begin for i in $1..$2 loop return next (i, nextval(''foo_rescan_seq'')); end loop; end;' LANGUAGE plpgsql; +CREATE FUNCTION foo_mat(int,int) RETURNS setof foo_rescan_t AS 'begin for i in $1..$2 loop return next (i, nextval(''foo_rescan_seq2'')); end loop; end;' LANGUAGE plpgsql; --invokes ExecReScanFunctionScan - all these cases should materialize the function only once -- LEFT JOIN on a condition that the planner can't prove to be true is used to ensure the function -- is on the inner path of a nestloop join -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_sql(11,13) ON (r+i)<100; @@ -498,10 +739,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_sql(11,13) ON (r+i)<100; 3 | 13 | 3 (9 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_sql(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100; @@ -518,10 +759,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_sql(11,13) WITH ORDINALITY 3 | 13 | 3 | 3 (9 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) ON (r+i)<100; @@ -538,10 +779,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) ON (r+i)<100; 3 | 13 | 3 (9 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100; @@ -558,6 +799,26 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) WITH ORDINALITY 3 | 13 | 3 | 3 (9 rows) +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 +(1 row) + +SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN TABLE( foo_sql(11,13), foo_mat(11,13) ) WITH ORDINALITY AS f(i1,s1,i2,s2,o) ON (r+i1+i2)<100; + r | i1 | s1 | i2 | s2 | o +---+----+----+----+----+--- + 1 | 11 | 1 | 11 | 1 | 1 + 1 | 12 | 2 | 12 | 2 | 2 + 1 | 13 | 3 | 13 | 3 | 3 + 2 | 11 | 1 | 11 | 1 | 1 + 2 | 12 | 2 | 12 | 2 | 2 + 2 | 13 | 3 | 13 | 3 | 3 + 3 | 11 | 1 | 11 | 1 | 1 + 3 | 12 | 2 | 12 | 2 | 2 + 3 | 13 | 3 | 13 | 3 | 3 +(9 rows) + SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) f(i) ON (r+i)<100; r | i ---+---- @@ -615,10 +876,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN unnest(array[10,20,30]) WITH O (9 rows) --invokes ExecReScanFunctionScan with chgParam != NULL (using implied LATERAL) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(10+r,13); @@ -632,10 +893,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(10+r,13); 3 | 13 | 6 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(10+r,13) WITH ORDINALITY AS f(i,s,o); @@ -649,10 +910,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(10+r,13) WITH ORDINALITY AS f(i 3 | 13 | 6 | 1 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(11,10+r); @@ -666,10 +927,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(11,10+r); 3 | 13 | 6 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(11,10+r) WITH ORDINALITY AS f(i,s,o); @@ -683,10 +944,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(11,10+r) WITH ORDINALITY AS f(i 3 | 13 | 6 | 3 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_sql(r1,r2); @@ -704,10 +965,10 @@ SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_sql(r1,r2); 16 | 20 | 20 | 10 (10 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_sql(r1,r2) WITH ORDINALITY AS f(i,s,o); @@ -725,10 +986,10 @@ SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_sql(r1,r2) WITH ORD 16 | 20 | 20 | 10 | 5 (10 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(10+r,13); @@ -742,10 +1003,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(10+r,13); 3 | 13 | 6 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(10+r,13) WITH ORDINALITY AS f(i,s,o); @@ -759,10 +1020,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(10+r,13) WITH ORDINALITY AS f(i 3 | 13 | 6 | 1 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(11,10+r); @@ -776,10 +1037,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(11,10+r); 3 | 13 | 6 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(11,10+r) WITH ORDINALITY AS f(i,s,o); @@ -793,10 +1054,10 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(11,10+r) WITH ORDINALITY AS f(i 3 | 13 | 6 | 3 (6 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2); @@ -814,10 +1075,10 @@ SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2); 16 | 20 | 20 | 10 (10 rows) -SELECT setval('foo_rescan_seq',1,false); - setval --------- - 1 +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 (1 row) SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2) WITH ORDINALITY AS f(i,s,o); @@ -835,6 +1096,82 @@ SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2) WITH ORD 16 | 20 | 20 | 10 | 5 (10 rows) +-- selective rescan of multiple functions: +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 +(1 row) + +SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(11,11), foo_mat(10+r,13) ); + r | i | s | i | s +---+----+---+----+--- + 1 | 11 | 1 | 11 | 1 + 1 | | | 12 | 2 + 1 | | | 13 | 3 + 2 | 11 | 1 | 12 | 4 + 2 | | | 13 | 5 + 3 | 11 | 1 | 13 | 6 +(6 rows) + +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 +(1 row) + +SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(10+r,13), foo_mat(11,11) ); + r | i | s | i | s +---+----+---+----+--- + 1 | 11 | 1 | 11 | 1 + 1 | 12 | 2 | | + 1 | 13 | 3 | | + 2 | 12 | 4 | 11 | 1 + 2 | 13 | 5 | | + 3 | 13 | 6 | 11 | 1 +(6 rows) + +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 +(1 row) + +SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(10+r,13), foo_mat(10+r,13) ); + r | i | s | i | s +---+----+---+----+--- + 1 | 11 | 1 | 11 | 1 + 1 | 12 | 2 | 12 | 2 + 1 | 13 | 3 | 13 | 3 + 2 | 12 | 4 | 12 | 4 + 2 | 13 | 5 | 13 | 5 + 3 | 13 | 6 | 13 | 6 +(6 rows) + +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); + setval | setval +--------+-------- + 1 | 1 +(1 row) + +SELECT * FROM generate_series(1,2) r1, generate_series(r1,3) r2, TABLE( foo_sql(10+r1,13), foo_mat(10+r2,13) ); + r1 | r2 | i | s | i | s +----+----+----+----+----+--- + 1 | 1 | 11 | 1 | 11 | 1 + 1 | 1 | 12 | 2 | 12 | 2 + 1 | 1 | 13 | 3 | 13 | 3 + 1 | 2 | 11 | 4 | 12 | 4 + 1 | 2 | 12 | 5 | 13 | 5 + 1 | 2 | 13 | 6 | | + 1 | 3 | 11 | 7 | 13 | 6 + 1 | 3 | 12 | 8 | | + 1 | 3 | 13 | 9 | | + 2 | 2 | 12 | 10 | 12 | 7 + 2 | 2 | 13 | 11 | 13 | 8 + 2 | 3 | 12 | 12 | 13 | 9 + 2 | 3 | 13 | 13 | | +(13 rows) + SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) f(i); r | i ---+---- @@ -1072,7 +1409,8 @@ SELECT * FROM (VALUES (1),(2),(3)) v1(r1), DROP FUNCTION foo_sql(int,int); DROP FUNCTION foo_mat(int,int); -DROP SEQUENCE foo_rescan_seq; +DROP SEQUENCE foo_rescan_seq1; +DROP SEQUENCE foo_rescan_seq2; -- -- Test cases involving OUT parameters -- @@ -1521,51 +1859,97 @@ LINE 1: select * from testfoo(); ^ drop function testfoo(); -- --- Check some cases involving dropped columns in a rowtype result +-- Check some cases involving added/dropped columns in a rowtype result -- -create temp table users (userid text, email text, todrop bool, enabled bool); -insert into users values ('id','email',true,true); -insert into users values ('id2','email2',true,true); +create temp table users (userid text, seq int, email text, todrop bool, moredrop int, enabled bool); +insert into users values ('id',1,'email',true,11,true); +insert into users values ('id2',2,'email2',true,12,true); alter table users drop column todrop; create or replace function get_first_user() returns users as $$ SELECT * FROM users ORDER BY userid LIMIT 1; $$ language sql stable; SELECT get_first_user(); - get_first_user ----------------- - (id,email,t) + get_first_user +------------------- + (id,1,email,11,t) (1 row) SELECT * FROM get_first_user(); - userid | email | enabled ---------+-------+--------- - id | email | t + userid | seq | email | moredrop | enabled +--------+-----+-------+----------+--------- + id | 1 | email | 11 | t (1 row) create or replace function get_users() returns setof users as $$ SELECT * FROM users ORDER BY userid; $$ language sql stable; SELECT get_users(); - get_users ----------------- - (id,email,t) - (id2,email2,t) + get_users +--------------------- + (id,1,email,11,t) + (id2,2,email2,12,t) (2 rows) SELECT * FROM get_users(); - userid | email | enabled ---------+--------+--------- - id | email | t - id2 | email2 | t + userid | seq | email | moredrop | enabled +--------+-----+--------+----------+--------- + id | 1 | email | 11 | t + id2 | 2 | email2 | 12 | t (2 rows) SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes - userid | email | enabled | ordinality ---------+--------+---------+------------ - id | email | t | 1 - id2 | email2 | t | 2 + userid | seq | email | moredrop | enabled | ordinality +--------+-----+--------+----------+---------+------------ + id | 1 | email | 11 | t | 1 + id2 | 2 | email2 | 12 | t | 2 +(2 rows) + +-- multiple functions vs. dropped columns +SELECT * FROM TABLE(generate_series(10,11), get_users()) WITH ORDINALITY; + generate_series | userid | seq | email | moredrop | enabled | ordinality +-----------------+--------+-----+--------+----------+---------+------------ + 10 | id | 1 | email | 11 | t | 1 + 11 | id2 | 2 | email2 | 12 | t | 2 +(2 rows) + +SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY; + userid | seq | email | moredrop | enabled | generate_series | ordinality +--------+-----+--------+----------+---------+-----------------+------------ + id | 1 | email | 11 | t | 10 | 1 + id2 | 2 | email2 | 12 | t | 11 | 2 +(2 rows) + +-- check that we can cope with post-parsing changes in rowtypes +create temp view usersview as +SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY; +select * from usersview; + userid | seq | email | moredrop | enabled | generate_series | ordinality +--------+-----+--------+----------+---------+-----------------+------------ + id | 1 | email | 11 | t | 10 | 1 + id2 | 2 | email2 | 12 | t | 11 | 2 +(2 rows) + +alter table users drop column moredrop; +select * from usersview; + userid | seq | email | moredrop | enabled | generate_series | ordinality +--------+-----+--------+----------+---------+-----------------+------------ + id | 1 | email | | t | 10 | 1 + id2 | 2 | email2 | | t | 11 | 2 +(2 rows) + +alter table users add column junk text; +select * from usersview; + userid | seq | email | moredrop | enabled | generate_series | ordinality +--------+-----+--------+----------+---------+-----------------+------------ + id | 1 | email | | t | 10 | 1 + id2 | 2 | email2 | | t | 11 | 2 (2 rows) +alter table users alter column seq type numeric; +select * from usersview; -- expect clean failure +ERROR: attribute 2 has wrong type +DETAIL: Table has type numeric, but query expects integer. +drop view usersview; drop function get_first_user(); drop function get_users(); drop table users; diff --git a/src/test/regress/sql/rangefuncs.sql b/src/test/regress/sql/rangefuncs.sql index e82a1d55712..7ba8cbb3042 100644 --- a/src/test/regress/sql/rangefuncs.sql +++ b/src/test/regress/sql/rangefuncs.sql @@ -16,14 +16,41 @@ select a,ord from unnest(array['a','b']) with ordinality as z(a,ord); select * from unnest(array['a','b']) with ordinality as z(a,ord); select a,ord from unnest(array[1.0::float8]) with ordinality as z(a,ord); select * from unnest(array[1.0::float8]) with ordinality as z(a,ord); +select row_to_json(s.*) from generate_series(11,14) with ordinality s; -- ordinality vs. views create temporary view vw_ord as select * from (values (1)) v(n) join foot(1) with ordinality as z(a,b,ord) on (n=ord); select * from vw_ord; select definition from pg_views where viewname='vw_ord'; drop view vw_ord; --- ordinality vs. rewind and reverse scan + +-- multiple functions +select * from table(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord); +create temporary view vw_ord as select * from (values (1)) v(n) join table(foot(1),foot(2)) with ordinality as z(a,b,c,d,ord) on (n=ord); +select * from vw_ord; +select definition from pg_views where viewname='vw_ord'; +drop view vw_ord; + +-- expansions of unnest() +select * from unnest(array[10,20],array['foo','bar'],array[1.0]); +select * from unnest(array[10,20],array['foo','bar'],array[1.0]) with ordinality as z(a,b,c,ord); +select * from table(unnest(array[10,20],array['foo','bar'],array[1.0])) with ordinality as z(a,b,c,ord); +select * from table(unnest(array[10,20],array['foo','bar']), generate_series(101,102)) with ordinality as z(a,b,c,ord); +create temporary view vw_ord as select * from unnest(array[10,20],array['foo','bar'],array[1.0]) as z(a,b,c); +select * from vw_ord; +select definition from pg_views where viewname='vw_ord'; +drop view vw_ord; +create temporary view vw_ord as select * from table(unnest(array[10,20],array['foo','bar'],array[1.0])) as z(a,b,c); +select * from vw_ord; +select definition from pg_views where viewname='vw_ord'; +drop view vw_ord; +create temporary view vw_ord as select * from table(unnest(array[10,20],array['foo','bar']), generate_series(1,2)) as z(a,b,c); +select * from vw_ord; +select definition from pg_views where viewname='vw_ord'; +drop view vw_ord; + +-- ordinality and multiple functions vs. rewind and reverse scan begin; -declare foo scroll cursor for select * from generate_series(1,5) with ordinality as g(i,o); +declare foo scroll cursor for select * from table(generate_series(1,5),generate_series(1,2)) with ordinality as g(i,j,o); fetch all from foo; fetch backward all from foo; fetch all from foo; @@ -31,6 +58,12 @@ fetch next from foo; fetch next from foo; fetch prior from foo; fetch absolute 1 from foo; +fetch next from foo; +fetch next from foo; +fetch next from foo; +fetch prior from foo; +fetch prior from foo; +fetch prior from foo; commit; -- function with implicit LATERAL @@ -57,133 +90,169 @@ INSERT INTO foo VALUES(1,2,'Ed'); INSERT INTO foo VALUES(2,1,'Mary'); -- sql, proretset = f, prorettype = b -CREATE FUNCTION getfoo(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo1(int) RETURNS int AS 'SELECT $1;' LANGUAGE SQL; +SELECT * FROM getfoo1(1) AS t1; +SELECT * FROM getfoo1(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo1(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY as t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo1(1) WITH ORDINALITY as t1(v,o); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- sql, proretset = t, prorettype = b -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo2(int) RETURNS setof int AS 'SELECT fooid FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo2(1) AS t1; +SELECT * FROM getfoo2(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo2(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo2(1) WITH ORDINALITY AS t1(v,o); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- sql, proretset = t, prorettype = b -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo3(int) RETURNS setof text AS 'SELECT fooname FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo3(1) AS t1; +SELECT * FROM getfoo3(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo3(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo3(1) WITH ORDINALITY AS t1(v,o); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- sql, proretset = f, prorettype = c -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo4(int) RETURNS foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo4(1) AS t1; +SELECT * FROM getfoo4(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo4(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo4(1) WITH ORDINALITY AS t1(a,b,c,o); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- sql, proretset = t, prorettype = c -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo5(int) RETURNS setof foo AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo5(1) AS t1; +SELECT * FROM getfoo5(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo5(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo5(1) WITH ORDINALITY AS t1(a,b,c,o); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; --- ordinality not supported for returns record yet -- sql, proretset = f, prorettype = record -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS +CREATE FUNCTION getfoo6(int) RETURNS RECORD AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo6(1) AS t1(fooid int, foosubid int, fooname text); +SELECT * FROM TABLE( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY; +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo6(1) AS (fooid int, foosubid int, fooname text); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; +CREATE VIEW vw_getfoo AS + SELECT * FROM TABLE( getfoo6(1) AS (fooid int, foosubid int, fooname text) ) + WITH ORDINALITY; +SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- sql, proretset = t, prorettype = record -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; -SELECT * FROM getfoo(1) AS t1(fooid int, foosubid int, fooname text); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) AS +CREATE FUNCTION getfoo7(int) RETURNS setof record AS 'SELECT * FROM foo WHERE fooid = $1;' LANGUAGE SQL; +SELECT * FROM getfoo7(1) AS t1(fooid int, foosubid int, fooname text); +SELECT * FROM TABLE( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) WITH ORDINALITY; +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo7(1) AS (fooid int, foosubid int, fooname text); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; +CREATE VIEW vw_getfoo AS + SELECT * FROM TABLE( getfoo7(1) AS (fooid int, foosubid int, fooname text) ) + WITH ORDINALITY; +SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- plpgsql, proretset = f, prorettype = b -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE plpgsql; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo8(int) RETURNS int AS 'DECLARE fooint int; BEGIN SELECT fooid into fooint FROM foo WHERE fooid = $1; RETURN fooint; END;' LANGUAGE plpgsql; +SELECT * FROM getfoo8(1) AS t1; +SELECT * FROM getfoo8(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo8(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(v,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo8(1) WITH ORDINALITY AS t1(v,o); SELECT * FROM vw_getfoo; +DROP VIEW vw_getfoo; -- plpgsql, proretset = f, prorettype = c -DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); -CREATE FUNCTION getfoo(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE plpgsql; -SELECT * FROM getfoo(1) AS t1; -SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1); +CREATE FUNCTION getfoo9(int) RETURNS foo AS 'DECLARE footup foo%ROWTYPE; BEGIN SELECT * into footup FROM foo WHERE fooid = $1; RETURN footup; END;' LANGUAGE plpgsql; +SELECT * FROM getfoo9(1) AS t1; +SELECT * FROM getfoo9(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo9(1); SELECT * FROM vw_getfoo; DROP VIEW vw_getfoo; -CREATE VIEW vw_getfoo AS SELECT * FROM getfoo(1) WITH ORDINALITY AS t1(a,b,c,o); +CREATE VIEW vw_getfoo AS SELECT * FROM getfoo9(1) WITH ORDINALITY AS t1(a,b,c,o); SELECT * FROM vw_getfoo; - DROP VIEW vw_getfoo; -DROP FUNCTION getfoo(int); + +-- mix 'n match kinds, to exercise expandRTE and related logic + +select * from table(getfoo1(1),getfoo2(1),getfoo3(1),getfoo4(1),getfoo5(1), + getfoo6(1) AS (fooid int, foosubid int, fooname text), + getfoo7(1) AS (fooid int, foosubid int, fooname text), + getfoo8(1),getfoo9(1)) + with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u); +select * from table(getfoo9(1),getfoo8(1), + getfoo7(1) AS (fooid int, foosubid int, fooname text), + getfoo6(1) AS (fooid int, foosubid int, fooname text), + getfoo5(1),getfoo4(1),getfoo3(1),getfoo2(1),getfoo1(1)) + with ordinality as t1(a,b,c,d,e,f,g,h,i,j,k,l,m,o,p,q,r,s,t,u); + +create temporary view vw_foo as + select * from table(getfoo9(1), + getfoo7(1) AS (fooid int, foosubid int, fooname text), + getfoo1(1)) + with ordinality as t1(a,b,c,d,e,f,g,n); +select * from vw_foo; +select pg_get_viewdef('vw_foo'); +drop view vw_foo; + +DROP FUNCTION getfoo1(int); +DROP FUNCTION getfoo2(int); +DROP FUNCTION getfoo3(int); +DROP FUNCTION getfoo4(int); +DROP FUNCTION getfoo5(int); +DROP FUNCTION getfoo6(int); +DROP FUNCTION getfoo7(int); +DROP FUNCTION getfoo8(int); +DROP FUNCTION getfoo9(int); DROP FUNCTION foot(int); DROP TABLE foo2; DROP TABLE foo; -- Rescan tests -- -CREATE TEMPORARY SEQUENCE foo_rescan_seq; +CREATE TEMPORARY SEQUENCE foo_rescan_seq1; +CREATE TEMPORARY SEQUENCE foo_rescan_seq2; CREATE TYPE foo_rescan_t AS (i integer, s bigint); -CREATE FUNCTION foo_sql(int,int) RETURNS setof foo_rescan_t AS 'SELECT i, nextval(''foo_rescan_seq'') FROM generate_series($1,$2) i;' LANGUAGE SQL; +CREATE FUNCTION foo_sql(int,int) RETURNS setof foo_rescan_t AS 'SELECT i, nextval(''foo_rescan_seq1'') FROM generate_series($1,$2) i;' LANGUAGE SQL; -- plpgsql functions use materialize mode -CREATE FUNCTION foo_mat(int,int) RETURNS setof foo_rescan_t AS 'begin for i in $1..$2 loop return next (i, nextval(''foo_rescan_seq'')); end loop; end;' LANGUAGE plpgsql; +CREATE FUNCTION foo_mat(int,int) RETURNS setof foo_rescan_t AS 'begin for i in $1..$2 loop return next (i, nextval(''foo_rescan_seq2'')); end loop; end;' LANGUAGE plpgsql; --invokes ExecReScanFunctionScan - all these cases should materialize the function only once -- LEFT JOIN on a condition that the planner can't prove to be true is used to ensure the function -- is on the inner path of a nestloop join -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_sql(11,13) ON (r+i)<100; -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_sql(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100; -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) ON (r+i)<100; -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN foo_mat(11,13) WITH ORDINALITY AS f(i,s,o) ON (r+i)<100; +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); +SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN TABLE( foo_sql(11,13), foo_mat(11,13) ) WITH ORDINALITY AS f(i1,s1,i2,s2,o) ON (r+i1+i2)<100; SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) f(i) ON (r+i)<100; SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN generate_series(11,13) WITH ORDINALITY AS f(i,o) ON (r+i)<100; @@ -193,32 +262,44 @@ SELECT * FROM (VALUES (1),(2),(3)) v(r) LEFT JOIN unnest(array[10,20,30]) WITH O --invokes ExecReScanFunctionScan with chgParam != NULL (using implied LATERAL) -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(10+r,13); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(10+r,13) WITH ORDINALITY AS f(i,s,o); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(11,10+r); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_sql(11,10+r) WITH ORDINALITY AS f(i,s,o); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_sql(r1,r2); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_sql(r1,r2) WITH ORDINALITY AS f(i,s,o); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(10+r,13); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(10+r,13) WITH ORDINALITY AS f(i,s,o); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(11,10+r); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (1),(2),(3)) v(r), foo_mat(11,10+r) WITH ORDINALITY AS f(i,s,o); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2); -SELECT setval('foo_rescan_seq',1,false); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); SELECT * FROM (VALUES (11,12),(13,15),(16,20)) v(r1,r2), foo_mat(r1,r2) WITH ORDINALITY AS f(i,s,o); +-- selective rescan of multiple functions: + +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); +SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(11,11), foo_mat(10+r,13) ); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); +SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(10+r,13), foo_mat(11,11) ); +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); +SELECT * FROM (VALUES (1),(2),(3)) v(r), TABLE( foo_sql(10+r,13), foo_mat(10+r,13) ); + +SELECT setval('foo_rescan_seq1',1,false),setval('foo_rescan_seq2',1,false); +SELECT * FROM generate_series(1,2) r1, generate_series(r1,3) r2, TABLE( foo_sql(10+r1,13), foo_mat(10+r2,13) ); + SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) f(i); SELECT * FROM (VALUES (1),(2),(3)) v(r), generate_series(10+r,20-r) WITH ORDINALITY AS f(i,o); @@ -242,7 +323,8 @@ SELECT * FROM (VALUES (1),(2),(3)) v1(r1), DROP FUNCTION foo_sql(int,int); DROP FUNCTION foo_mat(int,int); -DROP SEQUENCE foo_rescan_seq; +DROP SEQUENCE foo_rescan_seq1; +DROP SEQUENCE foo_rescan_seq2; -- -- Test cases involving OUT parameters @@ -444,12 +526,12 @@ select * from testfoo(); -- fail drop function testfoo(); -- --- Check some cases involving dropped columns in a rowtype result +-- Check some cases involving added/dropped columns in a rowtype result -- -create temp table users (userid text, email text, todrop bool, enabled bool); -insert into users values ('id','email',true,true); -insert into users values ('id2','email2',true,true); +create temp table users (userid text, seq int, email text, todrop bool, moredrop int, enabled bool); +insert into users values ('id',1,'email',true,11,true); +insert into users values ('id2',2,'email2',true,12,true); alter table users drop column todrop; create or replace function get_first_user() returns users as @@ -467,6 +549,23 @@ SELECT get_users(); SELECT * FROM get_users(); SELECT * FROM get_users() WITH ORDINALITY; -- make sure ordinality copes +-- multiple functions vs. dropped columns +SELECT * FROM TABLE(generate_series(10,11), get_users()) WITH ORDINALITY; +SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY; + +-- check that we can cope with post-parsing changes in rowtypes +create temp view usersview as +SELECT * FROM TABLE(get_users(), generate_series(10,11)) WITH ORDINALITY; + +select * from usersview; +alter table users drop column moredrop; +select * from usersview; +alter table users add column junk text; +select * from usersview; +alter table users alter column seq type numeric; +select * from usersview; -- expect clean failure + +drop view usersview; drop function get_first_user(); drop function get_users(); drop table users; |
