>From 8173640aec148d3c20e7089c4d04a040fa8867e2 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Wed, 3 Aug 2016 18:29:42 -0700
Subject: [PATCH 1/3] Add some more targetlist srf tests.

---
 src/test/regress/expected/tsrf.out | 156 +++++++++++++++++++++++++++++++++++++
 src/test/regress/parallel_schedule |   2 +-
 src/test/regress/serial_schedule   |   1 +
 src/test/regress/sql/tsrf.sql      |  56 +++++++++++++
 4 files changed, 214 insertions(+), 1 deletion(-)
 create mode 100644 src/test/regress/expected/tsrf.out
 create mode 100644 src/test/regress/sql/tsrf.sql

diff --git a/src/test/regress/expected/tsrf.out b/src/test/regress/expected/tsrf.out
new file mode 100644
index 0000000..119c046
--- /dev/null
+++ b/src/test/regress/expected/tsrf.out
@@ -0,0 +1,156 @@
+--
+-- tsrf - targetlist set returning function tests
+--
+-- simple srf
+SELECT generate_series(1, 3);
+ generate_series 
+-----------------
+               1
+               2
+               3
+(3 rows)
+
+-- parallel iteration
+SELECT generate_series(1, 3), generate_series(3,5);
+ generate_series | generate_series 
+-----------------+-----------------
+               1 |               3
+               2 |               4
+               3 |               5
+(3 rows)
+
+-- parallel iteration, different number of rows
+SELECT generate_series(1, 2), generate_series(1,4);
+ generate_series | generate_series 
+-----------------+-----------------
+               1 |               1
+               2 |               2
+               1 |               3
+               2 |               4
+(4 rows)
+
+-- srf, with SRF argument
+SELECT generate_series(1, generate_series(1, 3));
+ generate_series 
+-----------------
+               1
+               1
+               2
+               1
+               2
+               3
+(6 rows)
+
+-- srf, with two SRF arguments
+SELECT generate_series(generate_series(1,3), generate_series(2, 4));
+ERROR:  functions and operators can take at most one set argument
+CREATE TABLE few(id int, dataa text, datab text);
+INSERT INTO few VALUES(1, 'a', 'foo'),(2, 'a', 'bar'),(3, 'b', 'bar');
+-- SRF output order of sorting is maintained, if SRF is not referenced
+SELECT few.id, generate_series(1,3) g FROM few ORDER BY id DESC;
+ id | g 
+----+---
+  3 | 1
+  3 | 2
+  3 | 3
+  2 | 1
+  2 | 2
+  2 | 3
+  1 | 1
+  1 | 2
+  1 | 3
+(9 rows)
+
+-- but SRFs can be referenced in sort
+SELECT few.id, generate_series(1,3) g FROM few ORDER BY id, g DESC;
+ id | g 
+----+---
+  1 | 3
+  1 | 2
+  1 | 1
+  2 | 3
+  2 | 2
+  2 | 1
+  3 | 3
+  3 | 2
+  3 | 1
+(9 rows)
+
+-- SRFs are computed after aggregation
+SELECT few.dataa, count(*), min(id), max(id), generate_series(1,3) FROM few GROUP BY few.dataa;
+ dataa | count | min | max | generate_series 
+-------+-------+-----+-----+-----------------
+ b     |     1 |   3 |   3 |               1
+ b     |     1 |   3 |   3 |               2
+ b     |     1 |   3 |   3 |               3
+ a     |     2 |   1 |   2 |               1
+ a     |     2 |   1 |   2 |               2
+ a     |     2 |   1 |   2 |               3
+(6 rows)
+
+-- SRFs are computed after window functions
+SELECT id,lag(id) OVER(), count(*) OVER(), generate_series(1,3) FROM few;
+ id | lag | count | generate_series 
+----+-----+-------+-----------------
+  1 |     |     3 |               1
+  1 |     |     3 |               2
+  1 |     |     3 |               3
+  2 |   1 |     3 |               1
+  2 |   1 |     3 |               2
+  2 |   1 |     3 |               3
+  3 |   2 |     3 |               1
+  3 |   2 |     3 |               2
+  3 |   2 |     3 |               3
+(9 rows)
+
+-- sorting + grouping
+SELECT few.dataa, count(*), min(id), max(id), generate_series(1,3) FROM few GROUP BY few.dataa ORDER BY 5;
+ dataa | count | min | max | generate_series 
+-------+-------+-----+-----+-----------------
+ b     |     1 |   3 |   3 |               1
+ a     |     2 |   1 |   2 |               1
+ b     |     1 |   3 |   3 |               2
+ a     |     2 |   1 |   2 |               2
+ b     |     1 |   3 |   3 |               3
+ a     |     2 |   1 |   2 |               3
+(6 rows)
+
+-- grouping sets are a bit special, they produce NULLs in columns not actually NULL
+SELECT dataa, datab b, count(*) FROM few GROUP BY CUBE(dataa, datab) ORDER BY 1,2,3;
+ dataa |  b  | count 
+-------+-----+-------
+ a     | bar |     1
+ a     | foo |     1
+ a     |     |     2
+ b     | bar |     1
+ b     |     |     1
+       | bar |     2
+       | foo |     1
+       |     |     3
+(8 rows)
+
+-- data modification
+CREATE TABLE fewmore AS SELECT generate_series(1,3) AS data;
+INSERT INTO fewmore VALUES(generate_series(4,5));
+SELECT * FROM fewmore;
+ data 
+------
+    1
+    2
+    3
+    4
+    5
+(5 rows)
+
+-- nonsensically that seems to be allowed
+UPDATE fewmore SET data = generate_series(4,9);
+-- SRFs are now allowed in RETURNING
+INSERT INTO fewmore VALUES(1) RETURNING generate_series(1,3);
+ERROR:  set-valued function called in context that cannot accept a set
+-- nor aggregate arguments
+SELECT count(generate_series(1,3)) FROM few;
+ERROR:  set-valued function called in context that cannot accept a set
+-- nor proper VALUES
+VALUES(1, generate_series(1,2));
+ERROR:  set-valued function called in context that cannot accept a set
+-- test DISTINCT ON, LIMIT/OFFSET, correlated subqueries
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 4ebad04..46a119d 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -92,7 +92,7 @@ test: brin gin gist spgist privileges init_privs security_label collate matview
 test: alter_generic alter_operator misc psql async dbsize misc_functions
 
 # rules cannot run concurrently with any test that creates a view
-test: rules psql_crosstab select_parallel
+test: rules psql_crosstab select_parallel tsrf
 
 # ----------
 # Another group of parallel tests
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 5c7038d..1f2caa4 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -126,6 +126,7 @@ test: misc_functions
 test: rules
 test: psql_crosstab
 test: select_parallel
+test: tsrf
 test: select_views
 test: portals_p2
 test: foreign_key
diff --git a/src/test/regress/sql/tsrf.sql b/src/test/regress/sql/tsrf.sql
new file mode 100644
index 0000000..eb341bc
--- /dev/null
+++ b/src/test/regress/sql/tsrf.sql
@@ -0,0 +1,56 @@
+--
+-- tsrf - targetlist set returning function tests
+--
+
+-- simple srf
+SELECT generate_series(1, 3);
+
+-- parallel iteration
+SELECT generate_series(1, 3), generate_series(3,5);
+
+-- parallel iteration, different number of rows
+SELECT generate_series(1, 2), generate_series(1,4);
+
+-- srf, with SRF argument
+SELECT generate_series(1, generate_series(1, 3));
+
+-- srf, with two SRF arguments
+SELECT generate_series(generate_series(1,3), generate_series(2, 4));
+
+CREATE TABLE few(id int, dataa text, datab text);
+INSERT INTO few VALUES(1, 'a', 'foo'),(2, 'a', 'bar'),(3, 'b', 'bar');
+
+-- SRF output order of sorting is maintained, if SRF is not referenced
+SELECT few.id, generate_series(1,3) g FROM few ORDER BY id DESC;
+
+-- but SRFs can be referenced in sort
+SELECT few.id, generate_series(1,3) g FROM few ORDER BY id, g DESC;
+
+-- SRFs are computed after aggregation
+SELECT few.dataa, count(*), min(id), max(id), generate_series(1,3) FROM few GROUP BY few.dataa;
+
+-- SRFs are computed after window functions
+SELECT id,lag(id) OVER(), count(*) OVER(), generate_series(1,3) FROM few;
+
+-- sorting + grouping
+SELECT few.dataa, count(*), min(id), max(id), generate_series(1,3) FROM few GROUP BY few.dataa ORDER BY 5;
+
+-- grouping sets are a bit special, they produce NULLs in columns not actually NULL
+SELECT dataa, datab b, count(*) FROM few GROUP BY CUBE(dataa, datab) ORDER BY 1,2,3;
+
+-- data modification
+CREATE TABLE fewmore AS SELECT generate_series(1,3) AS data;
+INSERT INTO fewmore VALUES(generate_series(4,5));
+SELECT * FROM fewmore;
+
+-- nonsensically that seems to be allowed
+UPDATE fewmore SET data = generate_series(4,9);
+
+-- SRFs are now allowed in RETURNING
+INSERT INTO fewmore VALUES(1) RETURNING generate_series(1,3);
+-- nor aggregate arguments
+SELECT count(generate_series(1,3)) FROM few;
+-- nor proper VALUES
+VALUES(1, generate_series(1,2));
+
+-- test DISTINCT ON, LIMIT/OFFSET, correlated subqueries
-- 
2.8.1

