diff -w -U3 C:/cirrus/src/test/regress/expected/updatable_views.out C:/cirrus/build/testrun/regress/regress/results/updatable_views.out --- C:/cirrus/src/test/regress/expected/updatable_views.out 2024-03-20 22:41:29.034120800 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/updatable_views.out 2024-03-20 22:43:58.269077500 +0000 @@ -1089,2823 +1089,7 @@ WHEN MATCHED THEN UPDATE SET b = s.b WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b) RETURNING merge_action(), s.*, t.*; - merge_action | a | b | a | b ---------------+---+----+---+------- - DELETE | 1 | R1 | 1 | Row 1 - UPDATE | 2 | R2 | 2 | R2 - INSERT | 3 | R3 | 3 | R3 -(3 rows) - -SELECT * FROM base_tbl ORDER BY a; - a | b -----+-------- - -2 | Row -2 - -1 | Row -1 - 0 | Row 0 - 2 | R2 - 3 | R3 -(5 rows) - -EXPLAIN (costs off) UPDATE rw_view2 SET a=3 WHERE a=2; - QUERY PLAN ----------------------------------------------------------- - Update on rw_view1 rw_view1_1 - -> Subquery Scan on rw_view1 - Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2)) - -> Bitmap Heap Scan on base_tbl - Recheck Cond: (a > 0) - -> Bitmap Index Scan on base_tbl_pkey - Index Cond: (a > 0) -(7 rows) - -EXPLAIN (costs off) DELETE FROM rw_view2 WHERE a=2; - QUERY PLAN ----------------------------------------------------------- - Delete on rw_view1 rw_view1_1 - -> Subquery Scan on rw_view1 - Filter: ((rw_view1.a < 10) AND (rw_view1.a = 2)) - -> Bitmap Heap Scan on base_tbl - Recheck Cond: (a > 0) - -> Bitmap Index Scan on base_tbl_pkey - Index Cond: (a > 0) -(7 rows) - -EXPLAIN (costs off) -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED AND t.a <= 1 THEN DELETE - WHEN MATCHED THEN UPDATE SET b = s.b - WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b); - QUERY PLAN ------------------------------------------------------------- - Merge on rw_view1 rw_view1_1 - -> Hash Right Join - Hash Cond: (rw_view1.a = x.x) - -> Subquery Scan on rw_view1 - Filter: (rw_view1.a < 10) - -> Bitmap Heap Scan on base_tbl - Recheck Cond: (a > 0) - -> Bitmap Index Scan on base_tbl_pkey - Index Cond: (a > 0) - -> Hash - -> Function Scan on generate_series x -(11 rows) - --- MERGE with incomplete set of INSTEAD OF triggers -DROP TRIGGER rw_view1_del_trig ON rw_view1; -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED AND t.a <= 1 THEN DELETE - WHEN MATCHED THEN UPDATE SET b = s.b - WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b); -- should fail -ERROR: cannot delete from view "rw_view1" -DETAIL: Views containing LIMIT or OFFSET are not automatically updatable. -HINT: To enable deleting from the view using MERGE, provide an INSTEAD OF DELETE trigger. -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED THEN UPDATE SET b = s.b - WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b); -- ok -DROP TRIGGER rw_view1_ins_trig ON rw_view1; -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED THEN UPDATE SET b = s.b - WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b); -- should fail -ERROR: cannot insert into view "rw_view1" -DETAIL: Views containing LIMIT or OFFSET are not automatically updatable. -HINT: To enable inserting into the view using MERGE, provide an INSTEAD OF INSERT trigger. -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED THEN UPDATE SET b = s.b; -- ok --- MERGE with INSTEAD OF triggers on auto-updatable view -CREATE TRIGGER rw_view2_upd_trig INSTEAD OF UPDATE ON rw_view2 - FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn(); -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED THEN UPDATE SET b = s.b - WHEN NOT MATCHED AND s.a > 0 THEN INSERT VALUES (s.a, s.b); -- should fail -ERROR: cannot merge into view "rw_view2" -DETAIL: MERGE is not supported for views with INSTEAD OF triggers for some actions, but not others. -HINT: To enable merging into the view, either provide a full set of INSTEAD OF triggers or drop the existing INSTEAD OF triggers. -MERGE INTO rw_view2 t - USING (SELECT x, 'R'||x FROM generate_series(0,3) x) AS s(a,b) ON t.a = s.a - WHEN MATCHED THEN UPDATE SET b = s.b; -- ok -SELECT * FROM base_tbl ORDER BY a; - a | b -----+-------- - -2 | Row -2 - -1 | Row -1 - 0 | Row 0 - 1 | R1 - 2 | R2 - 3 | R3 -(6 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 -DROP FUNCTION rw_view1_trig_fn(); --- update using whole row from view -CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); -INSERT INTO base_tbl SELECT i, 'Row ' || i FROM generate_series(-2, 2) g(i); -CREATE VIEW rw_view1 AS SELECT b AS bb, a AS aa FROM base_tbl; -CREATE FUNCTION rw_view1_aa(x rw_view1) - RETURNS int AS $$ SELECT x.aa $$ LANGUAGE sql; -UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2 - RETURNING rw_view1_aa(v), v.bb; - rw_view1_aa | bb --------------+--------------- - 2 | Updated row 2 -(1 row) - -SELECT * FROM base_tbl; - a | b -----+--------------- - -2 | Row -2 - -1 | Row -1 - 0 | Row 0 - 1 | Row 1 - 2 | Updated row 2 -(5 rows) - -EXPLAIN (costs off) -UPDATE rw_view1 v SET bb='Updated row 2' WHERE rw_view1_aa(v)=2 - RETURNING rw_view1_aa(v), v.bb; - QUERY PLAN --------------------------------------------------- - Update on base_tbl - -> Index Scan using base_tbl_pkey on base_tbl - Index Cond: (a = 2) -(3 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to function rw_view1_aa(rw_view1) --- permissions checks -CREATE USER regress_view_user1; -CREATE USER regress_view_user2; -CREATE USER regress_view_user3; -SET SESSION AUTHORIZATION regress_view_user1; -CREATE TABLE base_tbl(a int, b text, c float); -INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0); -CREATE VIEW rw_view1 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl; -INSERT INTO rw_view1 VALUES ('Row 2', 2.0, 2); -GRANT SELECT ON base_tbl TO regress_view_user2; -GRANT SELECT ON rw_view1 TO regress_view_user2; -GRANT UPDATE (a,c) ON base_tbl TO regress_view_user2; -GRANT UPDATE (bb,cc) ON rw_view1 TO regress_view_user2; -RESET SESSION AUTHORIZATION; -SET SESSION AUTHORIZATION regress_view_user2; -CREATE VIEW rw_view2 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl; -SELECT * FROM base_tbl; -- ok - a | b | c ----+-------+--- - 1 | Row 1 | 1 - 2 | Row 2 | 2 -(2 rows) - -SELECT * FROM rw_view1; -- ok - bb | cc | aa --------+----+---- - Row 1 | 1 | 1 - Row 2 | 2 | 2 -(2 rows) - -SELECT * FROM rw_view2; -- ok - bb | cc | aa --------+----+---- - Row 1 | 1 | 1 - Row 2 | 2 | 2 -(2 rows) - -INSERT INTO base_tbl VALUES (3, 'Row 3', 3.0); -- not allowed -ERROR: permission denied for table base_tbl -INSERT INTO rw_view1 VALUES ('Row 3', 3.0, 3); -- not allowed -ERROR: permission denied for view rw_view1 -INSERT INTO rw_view2 VALUES ('Row 3', 3.0, 3); -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t - USING (VALUES ('Row 3', 3.0, 3)) AS v(b,c,a) ON t.aa = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.b, v.c, v.a); -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t - USING (VALUES ('Row 3', 3.0, 3)) AS v(b,c,a) ON t.aa = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.b, v.c, v.a); -- not allowed -ERROR: permission denied for table base_tbl -UPDATE base_tbl SET a=a, c=c; -- ok -UPDATE base_tbl SET b=b; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET bb=bb, cc=cc; -- ok -UPDATE rw_view1 SET aa=aa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET aa=aa, cc=cc; -- ok -UPDATE rw_view2 SET bb=bb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET bb = bb, cc = cc; -- ok -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET aa = aa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET aa = aa, cc = cc; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET bb = bb; -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM base_tbl; -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM rw_view1; -- not allowed -ERROR: permission denied for view rw_view1 -DELETE FROM rw_view2; -- not allowed -ERROR: permission denied for table base_tbl -RESET SESSION AUTHORIZATION; -SET SESSION AUTHORIZATION regress_view_user1; -GRANT INSERT, DELETE ON base_tbl TO regress_view_user2; -RESET SESSION AUTHORIZATION; -SET SESSION AUTHORIZATION regress_view_user2; -INSERT INTO base_tbl VALUES (3, 'Row 3', 3.0); -- ok -INSERT INTO rw_view1 VALUES ('Row 4', 4.0, 4); -- not allowed -ERROR: permission denied for view rw_view1 -INSERT INTO rw_view2 VALUES ('Row 4', 4.0, 4); -- ok -DELETE FROM base_tbl WHERE a=1; -- ok -DELETE FROM rw_view1 WHERE aa=2; -- not allowed -ERROR: permission denied for view rw_view1 -DELETE FROM rw_view2 WHERE aa=2; -- ok -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED AND bb = 'xxx' THEN DELETE; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED AND bb = 'xxx' THEN DELETE; -- ok -SELECT * FROM base_tbl; - a | b | c ----+-------+--- - 3 | Row 3 | 3 - 4 | Row 4 | 4 -(2 rows) - -RESET SESSION AUTHORIZATION; -SET SESSION AUTHORIZATION regress_view_user1; -REVOKE INSERT, DELETE ON base_tbl FROM regress_view_user2; -GRANT INSERT, DELETE ON rw_view1 TO regress_view_user2; -RESET SESSION AUTHORIZATION; -SET SESSION AUTHORIZATION regress_view_user2; -INSERT INTO base_tbl VALUES (5, 'Row 5', 5.0); -- not allowed -ERROR: permission denied for table base_tbl -INSERT INTO rw_view1 VALUES ('Row 5', 5.0, 5); -- ok -INSERT INTO rw_view2 VALUES ('Row 6', 6.0, 6); -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM base_tbl WHERE a=3; -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM rw_view1 WHERE aa=3; -- ok -DELETE FROM rw_view2 WHERE aa=4; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED AND bb = 'xxx' THEN DELETE; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED AND bb = 'xxx' THEN DELETE; -- not allowed -ERROR: permission denied for table base_tbl -SELECT * FROM base_tbl; - a | b | c ----+-------+--- - 4 | Row 4 | 4 - 5 | Row 5 | 5 -(2 rows) - -RESET SESSION AUTHORIZATION; -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 --- nested-view permissions -CREATE TABLE base_tbl(a int, b text, c float); -INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0); -SET SESSION AUTHORIZATION regress_view_user1; -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl; -SELECT * FROM rw_view1; -- not allowed -ERROR: permission denied for table base_tbl -SELECT * FROM rw_view1 FOR UPDATE; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET b = 'foo' WHERE a = 1; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user2; -CREATE VIEW rw_view2 AS SELECT * FROM rw_view1; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for view rw_view1 -SELECT * FROM rw_view2 FOR UPDATE; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET b = 'bar' WHERE a = 1; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for view rw_view1 -RESET SESSION AUTHORIZATION; -GRANT SELECT ON base_tbl TO regress_view_user1; -SET SESSION AUTHORIZATION regress_view_user1; -SELECT * FROM rw_view1; - a | b | c ----+-------+--- - 1 | Row 1 | 1 -(1 row) - -SELECT * FROM rw_view1 FOR UPDATE; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET b = 'foo' WHERE a = 1; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for view rw_view1 -SELECT * FROM rw_view2 FOR UPDATE; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET b = 'bar' WHERE a = 1; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for view rw_view1 -SET SESSION AUTHORIZATION regress_view_user1; -GRANT SELECT ON rw_view1 TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; - a | b | c ----+-------+--- - 1 | Row 1 | 1 -(1 row) - -SELECT * FROM rw_view2 FOR UPDATE; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET b = 'bar' WHERE a = 1; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for view rw_view1 -RESET SESSION AUTHORIZATION; -GRANT UPDATE ON base_tbl TO regress_view_user1; -SET SESSION AUTHORIZATION regress_view_user1; -SELECT * FROM rw_view1; - a | b | c ----+-------+--- - 1 | Row 1 | 1 -(1 row) - -SELECT * FROM rw_view1 FOR UPDATE; - a | b | c ----+-------+--- - 1 | Row 1 | 1 -(1 row) - -UPDATE rw_view1 SET b = 'foo' WHERE a = 1; -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; - a | b | c ----+-----+--- - 1 | foo | 1 -(1 row) - -SELECT * FROM rw_view2 FOR UPDATE; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET b = 'bar' WHERE a = 1; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'bar'; -- not allowed -ERROR: permission denied for view rw_view1 -SET SESSION AUTHORIZATION regress_view_user1; -GRANT UPDATE ON rw_view1 TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; - a | b | c ----+-----+--- - 1 | foo | 1 -(1 row) - -SELECT * FROM rw_view2 FOR UPDATE; - a | b | c ----+-----+--- - 1 | foo | 1 -(1 row) - -UPDATE rw_view2 SET b = 'bar' WHERE a = 1; -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'fud'; -RESET SESSION AUTHORIZATION; -REVOKE UPDATE ON base_tbl FROM regress_view_user1; -SET SESSION AUTHORIZATION regress_view_user1; -SELECT * FROM rw_view1; - a | b | c ----+-----+--- - 1 | fud | 1 -(1 row) - -SELECT * FROM rw_view1 FOR UPDATE; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET b = 'foo' WHERE a = 1; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; - a | b | c ----+-----+--- - 1 | fud | 1 -(1 row) - -SELECT * FROM rw_view2 FOR UPDATE; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET b = 'bar' WHERE a = 1; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET b = 'foo'; -- not allowed -ERROR: permission denied for table base_tbl -RESET SESSION AUTHORIZATION; -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 --- security invoker view permissions -SET SESSION AUTHORIZATION regress_view_user1; -CREATE TABLE base_tbl(a int, b text, c float); -INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0); -CREATE VIEW rw_view1 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl; -ALTER VIEW rw_view1 SET (security_invoker = true); -INSERT INTO rw_view1 VALUES ('Row 2', 2.0, 2); -GRANT SELECT ON rw_view1 TO regress_view_user2; -GRANT UPDATE (bb,cc) ON rw_view1 TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM base_tbl; -- not allowed -ERROR: permission denied for table base_tbl -SELECT * FROM rw_view1; -- not allowed -ERROR: permission denied for table base_tbl -INSERT INTO base_tbl VALUES (3, 'Row 3', 3.0); -- not allowed -ERROR: permission denied for table base_tbl -INSERT INTO rw_view1 VALUES ('Row 3', 3.0, 3); -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE base_tbl SET a=a; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET bb=bb, cc=cc; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET bb = bb; -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM base_tbl; -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM rw_view1; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN DELETE; -- not allowed -ERROR: permission denied for view rw_view1 -SET SESSION AUTHORIZATION regress_view_user1; -GRANT SELECT ON base_tbl TO regress_view_user2; -GRANT UPDATE (a,c) ON base_tbl TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM base_tbl; -- ok - a | b | c ----+-------+--- - 1 | Row 1 | 1 - 2 | Row 2 | 2 -(2 rows) - -SELECT * FROM rw_view1; -- ok - bb | cc | aa --------+----+---- - Row 1 | 1 | 1 - Row 2 | 2 | 2 -(2 rows) - -UPDATE base_tbl SET a=a, c=c; -- ok -UPDATE base_tbl SET b=b; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET cc=cc; -- ok -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET cc = cc; -- ok -UPDATE rw_view1 SET aa=aa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view1 SET bb=bb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET aa = aa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET bb = bb; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user1; -GRANT INSERT, DELETE ON base_tbl TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -INSERT INTO base_tbl VALUES (3, 'Row 3', 3.0); -- ok -INSERT INTO rw_view1 VALUES ('Row 4', 4.0, 4); -- not allowed -ERROR: permission denied for view rw_view1 -DELETE FROM base_tbl WHERE a=1; -- ok -DELETE FROM rw_view1 WHERE aa=2; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN DELETE; -- not allowed -ERROR: permission denied for view rw_view1 -SET SESSION AUTHORIZATION regress_view_user1; -REVOKE INSERT, DELETE ON base_tbl FROM regress_view_user2; -GRANT INSERT, DELETE ON rw_view1 TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -INSERT INTO rw_view1 VALUES ('Row 4', 4.0, 4); -- not allowed -ERROR: permission denied for table base_tbl -DELETE FROM rw_view1 WHERE aa=2; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN DELETE; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user1; -GRANT INSERT, DELETE ON base_tbl TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -INSERT INTO rw_view1 VALUES ('Row 4', 4.0, 4); -- ok -DELETE FROM rw_view1 WHERE aa=2; -- ok -MERGE INTO rw_view1 t USING (VALUES (3)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN DELETE; -- ok -SELECT * FROM base_tbl; -- ok - a | b | c ----+-------+--- - 4 | Row 4 | 4 -(1 row) - -RESET SESSION AUTHORIZATION; -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- ordinary view on top of security invoker view permissions -CREATE TABLE base_tbl(a int, b text, c float); -INSERT INTO base_tbl VALUES (1, 'Row 1', 1.0); -SET SESSION AUTHORIZATION regress_view_user1; -CREATE VIEW rw_view1 AS SELECT b AS bb, c AS cc, a AS aa FROM base_tbl; -ALTER VIEW rw_view1 SET (security_invoker = true); -SELECT * FROM rw_view1; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET aa=aa; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (2, 'Row 2', 2.0)) AS v(a,b,c) ON t.aa = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.b, v.c, v.a); -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user2; -CREATE VIEW rw_view2 AS SELECT cc AS ccc, aa AS aaa, bb AS bbb FROM rw_view1; -GRANT SELECT, UPDATE ON rw_view2 TO regress_view_user3; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (2, 'Row 2', 2.0)) AS v(a,b,c) ON t.aaa = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.c, v.a, v.b); -- not allowed -ERROR: permission denied for view rw_view1 -RESET SESSION AUTHORIZATION; -GRANT SELECT ON base_tbl TO regress_view_user1; -GRANT UPDATE (a, b) ON base_tbl TO regress_view_user1; -SET SESSION AUTHORIZATION regress_view_user1; -SELECT * FROM rw_view1; -- ok - bb | cc | aa --------+----+---- - Row 1 | 1 | 1 -(1 row) - -UPDATE rw_view1 SET aa=aa, bb=bb; -- ok -UPDATE rw_view1 SET cc=cc; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET aa = aa, bb = bb; -- ok -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET cc = cc; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -SET SESSION AUTHORIZATION regress_view_user3; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -SET SESSION AUTHORIZATION regress_view_user1; -GRANT SELECT ON rw_view1 TO regress_view_user2; -GRANT UPDATE (bb, cc) ON rw_view1 TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user3; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -RESET SESSION AUTHORIZATION; -GRANT SELECT ON base_tbl TO regress_view_user2; -GRANT UPDATE (a, c) ON base_tbl TO regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; -- ok - ccc | aaa | bbb ------+-----+------- - 1 | 1 | Row 1 -(1 row) - -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- ok -SET SESSION AUTHORIZATION regress_view_user3; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- not allowed -ERROR: permission denied for table base_tbl -RESET SESSION AUTHORIZATION; -GRANT SELECT ON base_tbl TO regress_view_user3; -GRANT UPDATE (a, c) ON base_tbl TO regress_view_user3; -SET SESSION AUTHORIZATION regress_view_user3; -SELECT * FROM rw_view2; -- ok - ccc | aaa | bbb ------+-----+------- - 1 | 1 | Row 1 -(1 row) - -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- ok -RESET SESSION AUTHORIZATION; -REVOKE SELECT, UPDATE ON base_tbl FROM regress_view_user1; -SET SESSION AUTHORIZATION regress_view_user1; -SELECT * FROM rw_view1; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view1 SET aa=aa; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.aa = v.a - WHEN MATCHED THEN UPDATE SET aa = aa; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; -- ok - ccc | aaa | bbb ------+-----+------- - 1 | 1 | Row 1 -(1 row) - -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- ok -SET SESSION AUTHORIZATION regress_view_user3; -SELECT * FROM rw_view2; -- ok - ccc | aaa | bbb ------+-----+------- - 1 | 1 | Row 1 -(1 row) - -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- ok -RESET SESSION AUTHORIZATION; -REVOKE SELECT, UPDATE ON base_tbl FROM regress_view_user2; -SET SESSION AUTHORIZATION regress_view_user2; -SELECT * FROM rw_view2; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- not allowed -ERROR: permission denied for table base_tbl -SET SESSION AUTHORIZATION regress_view_user3; -SELECT * FROM rw_view2; -- ok - ccc | aaa | bbb ------+-----+------- - 1 | 1 | Row 1 -(1 row) - -UPDATE rw_view2 SET aaa=aaa; -- not allowed -ERROR: permission denied for view rw_view1 -UPDATE rw_view2 SET bbb=bbb; -- not allowed -ERROR: permission denied for table base_tbl -UPDATE rw_view2 SET ccc=ccc; -- ok -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET aaa = aaa; -- not allowed -ERROR: permission denied for view rw_view1 -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET bbb = bbb; -- not allowed -ERROR: permission denied for table base_tbl -MERGE INTO rw_view2 t USING (VALUES (1)) AS v(a) ON t.aaa = v.a - WHEN MATCHED THEN UPDATE SET ccc = ccc; -- ok -RESET SESSION AUTHORIZATION; -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 -DROP USER regress_view_user1; -DROP USER regress_view_user2; -DROP USER regress_view_user3; --- column defaults -CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified', c serial); -INSERT INTO base_tbl VALUES (1, 'Row 1'); -INSERT INTO base_tbl VALUES (2, 'Row 2'); -INSERT INTO base_tbl VALUES (3); -CREATE VIEW rw_view1 AS SELECT a AS aa, b AS bb FROM base_tbl; -ALTER VIEW rw_view1 ALTER COLUMN bb SET DEFAULT 'View default'; -INSERT INTO rw_view1 VALUES (4, 'Row 4'); -INSERT INTO rw_view1 (aa) VALUES (5); -MERGE INTO rw_view1 t USING (VALUES (6)) AS v(a) ON t.aa = v.a - WHEN NOT MATCHED THEN INSERT (aa) VALUES (v.a); -SELECT * FROM base_tbl; - a | b | c ----+--------------+--- - 1 | Row 1 | 1 - 2 | Row 2 | 2 - 3 | Unspecified | 3 - 4 | Row 4 | 4 - 5 | View default | 5 - 6 | View default | 6 -(6 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- Table having triggers -CREATE TABLE base_tbl (a int PRIMARY KEY, b text DEFAULT 'Unspecified'); -INSERT INTO base_tbl VALUES (1, 'Row 1'); -INSERT INTO base_tbl VALUES (2, 'Row 2'); -CREATE FUNCTION rw_view1_trig_fn() -RETURNS trigger AS -$$ -BEGIN - IF TG_OP = 'INSERT' THEN - UPDATE base_tbl SET b=NEW.b WHERE a=1; - RETURN NULL; - END IF; - RETURN NULL; -END; -$$ -LANGUAGE plpgsql; -CREATE TRIGGER rw_view1_ins_trig AFTER INSERT ON base_tbl - FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn(); -CREATE VIEW rw_view1 AS SELECT a AS aa, b AS bb FROM base_tbl; -INSERT INTO rw_view1 VALUES (3, 'Row 3'); -select * from base_tbl; - a | b ----+------- - 2 | Row 2 - 3 | Row 3 - 1 | Row 3 -(3 rows) - -DROP VIEW rw_view1; -DROP TRIGGER rw_view1_ins_trig on base_tbl; -DROP FUNCTION rw_view1_trig_fn(); -DROP TABLE base_tbl; --- view with ORDER BY -CREATE TABLE base_tbl (a int, b int); -INSERT INTO base_tbl VALUES (1,2), (4,5), (3,-3); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl ORDER BY a+b; -SELECT * FROM rw_view1; - a | b ----+---- - 3 | -3 - 1 | 2 - 4 | 5 -(3 rows) - -INSERT INTO rw_view1 VALUES (7,-8); -SELECT * FROM rw_view1; - a | b ----+---- - 7 | -8 - 3 | -3 - 1 | 2 - 4 | 5 -(4 rows) - -EXPLAIN (verbose, costs off) UPDATE rw_view1 SET b = b + 1 RETURNING *; - QUERY PLAN -------------------------------------------------- - Update on public.base_tbl - Output: base_tbl.a, base_tbl.b - -> Seq Scan on public.base_tbl - Output: (base_tbl.b + 1), base_tbl.ctid -(4 rows) - -UPDATE rw_view1 SET b = b + 1 RETURNING *; - a | b ----+---- - 1 | 3 - 4 | 6 - 3 | -2 - 7 | -7 -(4 rows) - -SELECT * FROM rw_view1; - a | b ----+---- - 7 | -7 - 3 | -2 - 1 | 3 - 4 | 6 -(4 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- multiple array-column updates -CREATE TABLE base_tbl (a int, arr int[]); -INSERT INTO base_tbl VALUES (1,ARRAY[2]), (3,ARRAY[4]); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl; -UPDATE rw_view1 SET arr[1] = 42, arr[2] = 77 WHERE a = 3; -SELECT * FROM rw_view1; - a | arr ----+--------- - 1 | {2} - 3 | {42,77} -(2 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- views with updatable and non-updatable columns -CREATE TABLE base_tbl(a float); -INSERT INTO base_tbl SELECT i/10.0 FROM generate_series(1,10) g(i); -CREATE VIEW rw_view1 AS - SELECT ctid, sin(a) s, a, cos(a) c - FROM base_tbl - WHERE a != 0 - ORDER BY abs(a); -INSERT INTO rw_view1 VALUES (null, null, 1.1, null); -- should fail -ERROR: cannot insert into column "ctid" of view "rw_view1" -DETAIL: View columns that refer to system columns are not updatable. -INSERT INTO rw_view1 (s, c, a) VALUES (null, null, 1.1); -- should fail -ERROR: cannot insert into column "s" of view "rw_view1" -DETAIL: View columns that are not columns of their base relation are not updatable. -INSERT INTO rw_view1 (a) VALUES (1.1) RETURNING a, s, c; -- OK - a | s | c ------+-------------------+------------------- - 1.1 | 0.891207360061435 | 0.453596121425577 -(1 row) - -UPDATE rw_view1 SET s = s WHERE a = 1.1; -- should fail -ERROR: cannot update column "s" of view "rw_view1" -DETAIL: View columns that are not columns of their base relation are not updatable. -UPDATE rw_view1 SET a = 1.05 WHERE a = 1.1 RETURNING s; -- OK - s -------------------- - 0.867423225594017 -(1 row) - -DELETE FROM rw_view1 WHERE a = 1.05; -- OK -CREATE VIEW rw_view2 AS - SELECT s, c, s/c t, a base_a, ctid - FROM rw_view1; -INSERT INTO rw_view2 VALUES (null, null, null, 1.1, null); -- should fail -ERROR: cannot insert into column "t" of view "rw_view2" -DETAIL: View columns that are not columns of their base relation are not updatable. -INSERT INTO rw_view2(s, c, base_a) VALUES (null, null, 1.1); -- should fail -ERROR: cannot insert into column "s" of view "rw_view1" -DETAIL: View columns that are not columns of their base relation are not updatable. -INSERT INTO rw_view2(base_a) VALUES (1.1) RETURNING t; -- OK - t ------------------- - 1.96475965724865 -(1 row) - -UPDATE rw_view2 SET s = s WHERE base_a = 1.1; -- should fail -ERROR: cannot update column "s" of view "rw_view1" -DETAIL: View columns that are not columns of their base relation are not updatable. -UPDATE rw_view2 SET t = t WHERE base_a = 1.1; -- should fail -ERROR: cannot update column "t" of view "rw_view2" -DETAIL: View columns that are not columns of their base relation are not updatable. -UPDATE rw_view2 SET base_a = 1.05 WHERE base_a = 1.1; -- OK -DELETE FROM rw_view2 WHERE base_a = 1.05 RETURNING base_a, s, c, t; -- OK - base_a | s | c | t ---------+-------------------+-------------------+------------------ - 1.05 | 0.867423225594017 | 0.497571047891727 | 1.74331530998317 -(1 row) - -CREATE VIEW rw_view3 AS - SELECT s, c, s/c t, ctid - FROM rw_view1; -INSERT INTO rw_view3 VALUES (null, null, null, null); -- should fail -ERROR: cannot insert into column "t" of view "rw_view3" -DETAIL: View columns that are not columns of their base relation are not updatable. -INSERT INTO rw_view3(s) VALUES (null); -- should fail -ERROR: cannot insert into column "s" of view "rw_view1" -DETAIL: View columns that are not columns of their base relation are not updatable. -UPDATE rw_view3 SET s = s; -- should fail -ERROR: cannot update column "s" of view "rw_view1" -DETAIL: View columns that are not columns of their base relation are not updatable. -DELETE FROM rw_view3 WHERE s = sin(0.1); -- should be OK -SELECT * FROM base_tbl ORDER BY a; - a ------ - 0.2 - 0.3 - 0.4 - 0.5 - 0.6 - 0.7 - 0.8 - 0.9 - 1 -(9 rows) - -SELECT table_name, is_insertable_into - FROM information_schema.tables - WHERE table_name LIKE E'r_\\_view%' - ORDER BY table_name; - table_name | is_insertable_into -------------+-------------------- - rw_view1 | YES - rw_view2 | YES - rw_view3 | NO -(3 rows) - -SELECT table_name, is_updatable, is_insertable_into - FROM information_schema.views - WHERE table_name LIKE E'r_\\_view%' - ORDER BY table_name; - table_name | is_updatable | is_insertable_into -------------+--------------+-------------------- - rw_view1 | YES | YES - rw_view2 | YES | YES - rw_view3 | NO | NO -(3 rows) - -SELECT table_name, column_name, is_updatable - FROM information_schema.columns - WHERE table_name LIKE E'r_\\_view%' - ORDER BY table_name, ordinal_position; - table_name | column_name | is_updatable -------------+-------------+-------------- - rw_view1 | ctid | NO - rw_view1 | s | NO - rw_view1 | a | YES - rw_view1 | c | NO - rw_view2 | s | NO - rw_view2 | c | NO - rw_view2 | t | NO - rw_view2 | base_a | YES - rw_view2 | ctid | NO - rw_view3 | s | NO - rw_view3 | c | NO - rw_view3 | t | NO - rw_view3 | ctid | NO -(13 rows) - -SELECT events & 4 != 0 AS upd, - events & 8 != 0 AS ins, - events & 16 != 0 AS del - FROM pg_catalog.pg_relation_is_updatable('rw_view3'::regclass, false) t(events); - upd | ins | del ------+-----+----- - f | f | t -(1 row) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 -drop cascades to view rw_view3 --- view on table with GENERATED columns -CREATE TABLE base_tbl (id int, idplus1 int GENERATED ALWAYS AS (id + 1) STORED); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl; -INSERT INTO base_tbl (id) VALUES (1); -INSERT INTO rw_view1 (id) VALUES (2); -INSERT INTO base_tbl (id, idplus1) VALUES (3, DEFAULT); -INSERT INTO rw_view1 (id, idplus1) VALUES (4, DEFAULT); -INSERT INTO base_tbl (id, idplus1) VALUES (5, 6); -- error -ERROR: cannot insert a non-DEFAULT value into column "idplus1" -DETAIL: Column "idplus1" is a generated column. -INSERT INTO rw_view1 (id, idplus1) VALUES (6, 7); -- error -ERROR: cannot insert a non-DEFAULT value into column "idplus1" -DETAIL: Column "idplus1" is a generated column. -SELECT * FROM base_tbl; - id | idplus1 -----+--------- - 1 | 2 - 2 | 3 - 3 | 4 - 4 | 5 -(4 rows) - -UPDATE base_tbl SET id = 2000 WHERE id = 2; -UPDATE rw_view1 SET id = 3000 WHERE id = 3; -SELECT * FROM base_tbl; - id | idplus1 -------+--------- - 1 | 2 - 4 | 5 - 2000 | 2001 - 3000 | 3001 -(4 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- inheritance tests -CREATE TABLE base_tbl_parent (a int); -CREATE TABLE base_tbl_child (CHECK (a > 0)) INHERITS (base_tbl_parent); -INSERT INTO base_tbl_parent SELECT * FROM generate_series(-8, -1); -INSERT INTO base_tbl_child SELECT * FROM generate_series(1, 8); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl_parent; -CREATE VIEW rw_view2 AS SELECT * FROM ONLY base_tbl_parent; -SELECT * FROM rw_view1 ORDER BY a; - a ----- - -8 - -7 - -6 - -5 - -4 - -3 - -2 - -1 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -(16 rows) - -SELECT * FROM ONLY rw_view1 ORDER BY a; - a ----- - -8 - -7 - -6 - -5 - -4 - -3 - -2 - -1 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 -(16 rows) - -SELECT * FROM rw_view2 ORDER BY a; - a ----- - -8 - -7 - -6 - -5 - -4 - -3 - -2 - -1 -(8 rows) - -INSERT INTO rw_view1 VALUES (-100), (100); -INSERT INTO rw_view2 VALUES (-200), (200); -UPDATE rw_view1 SET a = a*10 WHERE a IN (-1, 1); -- Should produce -10 and 10 -UPDATE ONLY rw_view1 SET a = a*10 WHERE a IN (-2, 2); -- Should produce -20 and 20 -UPDATE rw_view2 SET a = a*10 WHERE a IN (-3, 3); -- Should produce -30 only -UPDATE ONLY rw_view2 SET a = a*10 WHERE a IN (-4, 4); -- Should produce -40 only -DELETE FROM rw_view1 WHERE a IN (-5, 5); -- Should delete -5 and 5 -DELETE FROM ONLY rw_view1 WHERE a IN (-6, 6); -- Should delete -6 and 6 -DELETE FROM rw_view2 WHERE a IN (-7, 7); -- Should delete -7 only -DELETE FROM ONLY rw_view2 WHERE a IN (-8, 8); -- Should delete -8 only -SELECT * FROM ONLY base_tbl_parent ORDER BY a; - a ------- - -200 - -100 - -40 - -30 - -20 - -10 - 100 - 200 -(8 rows) - -SELECT * FROM base_tbl_child ORDER BY a; - a ----- - 3 - 4 - 7 - 8 - 10 - 20 -(6 rows) - -MERGE INTO rw_view1 t USING (VALUES (-200), (10)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a+1; -- Should produce -199 and 11 -MERGE INTO ONLY rw_view1 t USING (VALUES (-100), (20)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a+1; -- Should produce -99 and 21 -MERGE INTO rw_view2 t USING (VALUES (-40), (3)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a+1; -- Should produce -39 only -MERGE INTO ONLY rw_view2 t USING (VALUES (-30), (4)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a+1; -- Should produce -29 only -SELECT * FROM ONLY base_tbl_parent ORDER BY a; - a ------- - -199 - -99 - -39 - -29 - -20 - -10 - 100 - 200 -(8 rows) - -SELECT * FROM base_tbl_child ORDER BY a; - a ----- - 3 - 4 - 7 - 8 - 11 - 21 -(6 rows) - -CREATE TABLE other_tbl_parent (id int); -CREATE TABLE other_tbl_child () INHERITS (other_tbl_parent); -INSERT INTO other_tbl_parent VALUES (7),(200); -INSERT INTO other_tbl_child VALUES (8),(100); -EXPLAIN (costs off) -UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id; - QUERY PLAN -------------------------------------------------------------------------- - Update on base_tbl_parent - Update on base_tbl_parent base_tbl_parent_1 - Update on base_tbl_child base_tbl_parent_2 - -> Merge Join - Merge Cond: (base_tbl_parent.a = other_tbl_parent.id) - -> Sort - Sort Key: base_tbl_parent.a - -> Append - -> Seq Scan on base_tbl_parent base_tbl_parent_1 - -> Seq Scan on base_tbl_child base_tbl_parent_2 - -> Sort - Sort Key: other_tbl_parent.id - -> Append - -> Seq Scan on other_tbl_parent other_tbl_parent_1 - -> Seq Scan on other_tbl_child other_tbl_parent_2 -(15 rows) - -UPDATE rw_view1 SET a = a + 1000 FROM other_tbl_parent WHERE a = id; -SELECT * FROM ONLY base_tbl_parent ORDER BY a; - a ------- - -199 - -99 - -39 - -29 - -20 - -10 - 1100 - 1200 -(8 rows) - -SELECT * FROM base_tbl_child ORDER BY a; - a ------- - 3 - 4 - 11 - 21 - 1007 - 1008 -(6 rows) - -DROP TABLE base_tbl_parent, base_tbl_child CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 -DROP TABLE other_tbl_parent CASCADE; -NOTICE: drop cascades to table other_tbl_child --- simple WITH CHECK OPTION -CREATE TABLE base_tbl (a int, b int DEFAULT 10); -INSERT INTO base_tbl VALUES (1,2), (2,3), (1,-1); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a < b - WITH LOCAL CHECK OPTION; -\d+ rw_view1 - View "public.rw_view1" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - a | integer | | | | plain | - b | integer | | | | plain | -View definition: - SELECT a, - b - FROM base_tbl - WHERE a < b; -Options: check_option=local - -SELECT * FROM information_schema.views WHERE table_name = 'rw_view1'; - table_catalog | table_schema | table_name | view_definition | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into ----------------+--------------+------------+------------------+--------------+--------------+--------------------+----------------------+----------------------+---------------------------- - regression | public | rw_view1 | SELECT a, +| LOCAL | YES | YES | NO | NO | NO - | | | b +| | | | | | - | | | FROM base_tbl+| | | | | | - | | | WHERE (a < b); | | | | | | -(1 row) - -INSERT INTO rw_view1 VALUES(3,4); -- ok -INSERT INTO rw_view1 VALUES(4,3); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (4, 3). -INSERT INTO rw_view1 VALUES(5,null); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (5, null). -UPDATE rw_view1 SET b = 5 WHERE a = 3; -- ok -UPDATE rw_view1 SET b = -5 WHERE a = 3; -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (3, -5). -INSERT INTO rw_view1(a) VALUES (9); -- ok -INSERT INTO rw_view1(a) VALUES (10); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (10, 10). -SELECT * FROM base_tbl ORDER BY a, b; - a | b ----+---- - 1 | -1 - 1 | 2 - 2 | 3 - 3 | 5 - 9 | 10 -(5 rows) - -MERGE INTO rw_view1 t USING (VALUES (10)) AS v(a) ON t.a = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.a, v.a + 1); -- ok -MERGE INTO rw_view1 t USING (VALUES (11)) AS v(a) ON t.a = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.a, v.a - 1); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (11, 10). -MERGE INTO rw_view1 t USING (VALUES (1)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a - 1; -- ok -MERGE INTO rw_view1 t USING (VALUES (2)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a + 1; -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (3, 3). -SELECT * FROM base_tbl ORDER BY a, b; - a | b -----+---- - 0 | 2 - 1 | -1 - 2 | 3 - 3 | 5 - 9 | 10 - 10 | 11 -(6 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- WITH LOCAL/CASCADED CHECK OPTION -CREATE TABLE base_tbl (a int); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a > 0; -CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a < 10 - WITH CHECK OPTION; -- implicitly cascaded -\d+ rw_view2 - View "public.rw_view2" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - a | integer | | | | plain | -View definition: - SELECT a - FROM rw_view1 - WHERE a < 10; -Options: check_option=cascaded - -SELECT * FROM information_schema.views WHERE table_name = 'rw_view2'; - table_catalog | table_schema | table_name | view_definition | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into ----------------+--------------+------------+-------------------+--------------+--------------+--------------------+----------------------+----------------------+---------------------------- - regression | public | rw_view2 | SELECT a +| CASCADED | YES | YES | NO | NO | NO - | | | FROM rw_view1 +| | | | | | - | | | WHERE (a < 10); | | | | | | -(1 row) - -INSERT INTO rw_view2 VALUES (-5); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (-5). -INSERT INTO rw_view2 VALUES (5); -- ok -INSERT INTO rw_view2 VALUES (15); -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (15). -SELECT * FROM base_tbl; - a ---- - 5 -(1 row) - -UPDATE rw_view2 SET a = a - 10; -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (-5). -UPDATE rw_view2 SET a = a + 10; -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (15). -CREATE OR REPLACE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a < 10 - WITH LOCAL CHECK OPTION; -\d+ rw_view2 - View "public.rw_view2" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - a | integer | | | | plain | -View definition: - SELECT a - FROM rw_view1 - WHERE a < 10; -Options: check_option=local - -SELECT * FROM information_schema.views WHERE table_name = 'rw_view2'; - table_catalog | table_schema | table_name | view_definition | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into ----------------+--------------+------------+-------------------+--------------+--------------+--------------------+----------------------+----------------------+---------------------------- - regression | public | rw_view2 | SELECT a +| LOCAL | YES | YES | NO | NO | NO - | | | FROM rw_view1 +| | | | | | - | | | WHERE (a < 10); | | | | | | -(1 row) - -INSERT INTO rw_view2 VALUES (-10); -- ok, but not in view -INSERT INTO rw_view2 VALUES (20); -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (20). -SELECT * FROM base_tbl; - a ------ - 5 - -10 -(2 rows) - -ALTER VIEW rw_view1 SET (check_option=here); -- invalid -ERROR: invalid value for enum option "check_option": here -DETAIL: Valid values are "local" and "cascaded". -ALTER VIEW rw_view1 SET (check_option=local); -INSERT INTO rw_view2 VALUES (-20); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (-20). -INSERT INTO rw_view2 VALUES (30); -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (30). -ALTER VIEW rw_view2 RESET (check_option); -\d+ rw_view2 - View "public.rw_view2" - Column | Type | Collation | Nullable | Default | Storage | Description ---------+---------+-----------+----------+---------+---------+------------- - a | integer | | | | plain | -View definition: - SELECT a - FROM rw_view1 - WHERE a < 10; - -SELECT * FROM information_schema.views WHERE table_name = 'rw_view2'; - table_catalog | table_schema | table_name | view_definition | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into ----------------+--------------+------------+-------------------+--------------+--------------+--------------------+----------------------+----------------------+---------------------------- - regression | public | rw_view2 | SELECT a +| NONE | YES | YES | NO | NO | NO - | | | FROM rw_view1 +| | | | | | - | | | WHERE (a < 10); | | | | | | -(1 row) - -INSERT INTO rw_view2 VALUES (30); -- ok, but not in view -SELECT * FROM base_tbl; - a ------ - 5 - -10 - 30 -(3 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 --- WITH CHECK OPTION with no local view qual -CREATE TABLE base_tbl (a int); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WITH CHECK OPTION; -CREATE VIEW rw_view2 AS SELECT * FROM rw_view1 WHERE a > 0; -CREATE VIEW rw_view3 AS SELECT * FROM rw_view2 WITH CHECK OPTION; -SELECT * FROM information_schema.views WHERE table_name LIKE E'rw\\_view_' ORDER BY table_name; - table_catalog | table_schema | table_name | view_definition | check_option | is_updatable | is_insertable_into | is_trigger_updatable | is_trigger_deletable | is_trigger_insertable_into ----------------+--------------+------------+-------------------+--------------+--------------+--------------------+----------------------+----------------------+---------------------------- - regression | public | rw_view1 | SELECT a +| CASCADED | YES | YES | NO | NO | NO - | | | FROM base_tbl; | | | | | | - regression | public | rw_view2 | SELECT a +| NONE | YES | YES | NO | NO | NO - | | | FROM rw_view1 +| | | | | | - | | | WHERE (a > 0); | | | | | | - regression | public | rw_view3 | SELECT a +| CASCADED | YES | YES | NO | NO | NO - | | | FROM rw_view2; | | | | | | -(3 rows) - -INSERT INTO rw_view1 VALUES (-1); -- ok -INSERT INTO rw_view1 VALUES (1); -- ok -INSERT INTO rw_view2 VALUES (-2); -- ok, but not in view -INSERT INTO rw_view2 VALUES (2); -- ok -INSERT INTO rw_view3 VALUES (-3); -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (-3). -INSERT INTO rw_view3 VALUES (3); -- ok -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 -drop cascades to view rw_view3 --- WITH CHECK OPTION with scalar array ops -CREATE TABLE base_tbl (a int, b int[]); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a = ANY (b) - WITH CHECK OPTION; -INSERT INTO rw_view1 VALUES (1, ARRAY[1,2,3]); -- ok -INSERT INTO rw_view1 VALUES (10, ARRAY[4,5]); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (10, {4,5}). -UPDATE rw_view1 SET b[2] = -b[2] WHERE a = 1; -- ok -UPDATE rw_view1 SET b[1] = -b[1] WHERE a = 1; -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (1, {-1,-2,3}). -PREPARE ins(int, int[]) AS INSERT INTO rw_view1 VALUES($1, $2); -EXECUTE ins(2, ARRAY[1,2,3]); -- ok -EXECUTE ins(10, ARRAY[4,5]); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (10, {4,5}). -DEALLOCATE PREPARE ins; -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- WITH CHECK OPTION with subquery -CREATE TABLE base_tbl (a int); -CREATE TABLE ref_tbl (a int PRIMARY KEY); -INSERT INTO ref_tbl SELECT * FROM generate_series(1,10); -CREATE VIEW rw_view1 AS - SELECT * FROM base_tbl b - WHERE EXISTS(SELECT 1 FROM ref_tbl r WHERE r.a = b.a) - WITH CHECK OPTION; -INSERT INTO rw_view1 VALUES (5); -- ok -INSERT INTO rw_view1 VALUES (15); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (15). -UPDATE rw_view1 SET a = a + 5; -- ok -UPDATE rw_view1 SET a = a + 5; -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (15). -EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (5); - QUERY PLAN ---------------------------------------------------------- - Insert on base_tbl b - -> Result - SubPlan 1 - -> Index Only Scan using ref_tbl_pkey on ref_tbl r - Index Cond: (a = b.a) -(5 rows) - -EXPLAIN (costs off) UPDATE rw_view1 SET a = a + 5; - QUERY PLAN ------------------------------------------------------------ - Update on base_tbl b - -> Hash Join - Hash Cond: (b.a = r.a) - -> Seq Scan on base_tbl b - -> Hash - -> Seq Scan on ref_tbl r - SubPlan 1 - -> Index Only Scan using ref_tbl_pkey on ref_tbl r_1 - Index Cond: (a = b.a) -(9 rows) - -DROP TABLE base_tbl, ref_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- WITH CHECK OPTION with BEFORE trigger on base table -CREATE TABLE base_tbl (a int, b int); -CREATE FUNCTION base_tbl_trig_fn() -RETURNS trigger AS -$$ -BEGIN - NEW.b := 10; - RETURN NEW; -END; -$$ -LANGUAGE plpgsql; -CREATE TRIGGER base_tbl_trig BEFORE INSERT OR UPDATE ON base_tbl - FOR EACH ROW EXECUTE PROCEDURE base_tbl_trig_fn(); -CREATE VIEW rw_view1 AS SELECT * FROM base_tbl WHERE a < b WITH CHECK OPTION; -INSERT INTO rw_view1 VALUES (5,0); -- ok -INSERT INTO rw_view1 VALUES (15, 20); -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (15, 10). -UPDATE rw_view1 SET a = 20, b = 30; -- should fail -ERROR: new row violates check option for view "rw_view1" -DETAIL: Failing row contains (20, 10). -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 -DROP FUNCTION base_tbl_trig_fn(); --- WITH LOCAL CHECK OPTION with INSTEAD OF trigger on base view -CREATE TABLE base_tbl (a int, b int); -CREATE VIEW rw_view1 AS SELECT a FROM base_tbl WHERE a < b; -CREATE FUNCTION rw_view1_trig_fn() -RETURNS trigger AS -$$ -BEGIN - IF TG_OP = 'INSERT' THEN - INSERT INTO base_tbl VALUES (NEW.a, 10); - RETURN NEW; - ELSIF TG_OP = 'UPDATE' THEN - UPDATE base_tbl SET a=NEW.a WHERE a=OLD.a; - RETURN NEW; - ELSIF TG_OP = 'DELETE' THEN - DELETE FROM base_tbl WHERE a=OLD.a; - RETURN OLD; - END IF; -END; -$$ -LANGUAGE plpgsql; -CREATE TRIGGER rw_view1_trig - INSTEAD OF INSERT OR UPDATE OR DELETE ON rw_view1 - FOR EACH ROW EXECUTE PROCEDURE rw_view1_trig_fn(); -CREATE VIEW rw_view2 AS - SELECT * FROM rw_view1 WHERE a > 0 WITH LOCAL CHECK OPTION; -INSERT INTO rw_view2 VALUES (-5); -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (-5). -MERGE INTO rw_view2 t USING (VALUES (-5)) AS v(a) ON t.a = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.a); -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (-5). -INSERT INTO rw_view2 VALUES (5); -- ok -MERGE INTO rw_view2 t USING (VALUES (6)) AS v(a) ON t.a = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.a); -- ok -INSERT INTO rw_view2 VALUES (50); -- ok, but not in view -MERGE INTO rw_view2 t USING (VALUES (60)) AS v(a) ON t.a = v.a - WHEN NOT MATCHED THEN INSERT VALUES (v.a); -- ok, but not in view -UPDATE rw_view2 SET a = a - 10; -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (-5). -MERGE INTO rw_view2 t USING (VALUES (6)) AS v(a) ON t.a = v.a - WHEN MATCHED THEN UPDATE SET a = t.a - 10; -- should fail -ERROR: new row violates check option for view "rw_view2" -DETAIL: Failing row contains (-4). -SELECT * FROM base_tbl; - a | b -----+---- - 5 | 10 - 6 | 10 - 50 | 10 - 60 | 10 -(4 rows) - --- Check option won't cascade down to base view with INSTEAD OF triggers -ALTER VIEW rw_view2 SET (check_option=cascaded); -INSERT INTO rw_view2 VALUES (100); -- ok, but not in view (doesn't fail rw_view1's check) -UPDATE rw_view2 SET a = 200 WHERE a = 5; -- ok, but not in view (doesn't fail rw_view1's check) -SELECT * FROM base_tbl; - a | b ------+---- - 6 | 10 - 50 | 10 - 60 | 10 - 100 | 10 - 200 | 10 -(5 rows) - --- Neither local nor cascaded check options work with INSTEAD rules -DROP TRIGGER rw_view1_trig ON rw_view1; -CREATE RULE rw_view1_ins_rule AS ON INSERT TO rw_view1 - DO INSTEAD INSERT INTO base_tbl VALUES (NEW.a, 10); -CREATE RULE rw_view1_upd_rule AS ON UPDATE TO rw_view1 - DO INSTEAD UPDATE base_tbl SET a=NEW.a WHERE a=OLD.a; -INSERT INTO rw_view2 VALUES (-10); -- ok, but not in view (doesn't fail rw_view2's check) -INSERT INTO rw_view2 VALUES (5); -- ok -INSERT INTO rw_view2 VALUES (20); -- ok, but not in view (doesn't fail rw_view1's check) -UPDATE rw_view2 SET a = 30 WHERE a = 5; -- ok, but not in view (doesn't fail rw_view1's check) -INSERT INTO rw_view2 VALUES (5); -- ok -UPDATE rw_view2 SET a = -5 WHERE a = 5; -- ok, but not in view (doesn't fail rw_view2's check) -SELECT * FROM base_tbl; - a | b ------+---- - 6 | 10 - 50 | 10 - 60 | 10 - 100 | 10 - 200 | 10 - -10 | 10 - 20 | 10 - 30 | 10 - -5 | 10 -(9 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 -DROP FUNCTION rw_view1_trig_fn(); -CREATE TABLE base_tbl (a int); -CREATE VIEW rw_view1 AS SELECT a,10 AS b FROM base_tbl; -CREATE RULE rw_view1_ins_rule AS ON INSERT TO rw_view1 - DO INSTEAD INSERT INTO base_tbl VALUES (NEW.a); -CREATE VIEW rw_view2 AS - SELECT * FROM rw_view1 WHERE a > b WITH LOCAL CHECK OPTION; -INSERT INTO rw_view2 VALUES (2,3); -- ok, but not in view (doesn't fail rw_view2's check) -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 --- security barrier view -CREATE TABLE base_tbl (person text, visibility text); -INSERT INTO base_tbl VALUES ('Tom', 'public'), - ('Dick', 'private'), - ('Harry', 'public'); -CREATE VIEW rw_view1 AS - SELECT person FROM base_tbl WHERE visibility = 'public'; -CREATE FUNCTION snoop(anyelement) -RETURNS boolean AS -$$ -BEGIN - RAISE NOTICE 'snooped value: %', $1; - RETURN true; -END; -$$ -LANGUAGE plpgsql COST 0.000001; -CREATE OR REPLACE FUNCTION leakproof(anyelement) -RETURNS boolean AS -$$ -BEGIN - RETURN true; -END; -$$ -LANGUAGE plpgsql STRICT IMMUTABLE LEAKPROOF; -SELECT * FROM rw_view1 WHERE snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Dick -NOTICE: snooped value: Harry - person --------- - Tom - Harry -(2 rows) - -UPDATE rw_view1 SET person=person WHERE snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Dick -NOTICE: snooped value: Harry -DELETE FROM rw_view1 WHERE NOT snoop(person); -NOTICE: snooped value: Dick -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -ALTER VIEW rw_view1 SET (security_barrier = true); -SELECT table_name, is_insertable_into - FROM information_schema.tables - WHERE table_name = 'rw_view1'; - table_name | is_insertable_into -------------+-------------------- - rw_view1 | YES -(1 row) - -SELECT table_name, is_updatable, is_insertable_into - FROM information_schema.views - WHERE table_name = 'rw_view1'; - table_name | is_updatable | is_insertable_into -------------+--------------+-------------------- - rw_view1 | YES | YES -(1 row) - -SELECT table_name, column_name, is_updatable - FROM information_schema.columns - WHERE table_name = 'rw_view1' - ORDER BY ordinal_position; - table_name | column_name | is_updatable -------------+-------------+-------------- - rw_view1 | person | YES -(1 row) - -SELECT * FROM rw_view1 WHERE snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry - person --------- - Tom - Harry -(2 rows) - -UPDATE rw_view1 SET person=person WHERE snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -DELETE FROM rw_view1 WHERE NOT snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -MERGE INTO rw_view1 t - USING (VALUES ('Tom'), ('Dick'), ('Harry')) AS v(person) ON t.person = v.person - WHEN MATCHED AND snoop(t.person) THEN UPDATE SET person = v.person; -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -EXPLAIN (costs off) SELECT * FROM rw_view1 WHERE snoop(person); - QUERY PLAN ------------------------------------------------ - Subquery Scan on rw_view1 - Filter: snoop(rw_view1.person) - -> Seq Scan on base_tbl - Filter: (visibility = 'public'::text) -(4 rows) - -EXPLAIN (costs off) UPDATE rw_view1 SET person=person WHERE snoop(person); - QUERY PLAN -------------------------------------------------------------------- - Update on base_tbl - -> Seq Scan on base_tbl - Filter: ((visibility = 'public'::text) AND snoop(person)) -(3 rows) - -EXPLAIN (costs off) DELETE FROM rw_view1 WHERE NOT snoop(person); - QUERY PLAN -------------------------------------------------------------------------- - Delete on base_tbl - -> Seq Scan on base_tbl - Filter: ((visibility = 'public'::text) AND (NOT snoop(person))) -(3 rows) - -EXPLAIN (costs off) -MERGE INTO rw_view1 t - USING (VALUES ('Tom'), ('Dick'), ('Harry')) AS v(person) ON t.person = v.person - WHEN MATCHED AND snoop(t.person) THEN UPDATE SET person = v.person; - QUERY PLAN -------------------------------------------------------------- - Merge on base_tbl - -> Nested Loop - Join Filter: (base_tbl.person = "*VALUES*".column1) - -> Seq Scan on base_tbl - Filter: (visibility = 'public'::text) - -> Materialize - -> Values Scan on "*VALUES*" -(7 rows) - --- security barrier view on top of security barrier view -CREATE VIEW rw_view2 WITH (security_barrier = true) AS - SELECT * FROM rw_view1 WHERE snoop(person); -SELECT table_name, is_insertable_into - FROM information_schema.tables - WHERE table_name = 'rw_view2'; - table_name | is_insertable_into -------------+-------------------- - rw_view2 | YES -(1 row) - -SELECT table_name, is_updatable, is_insertable_into - FROM information_schema.views - WHERE table_name = 'rw_view2'; - table_name | is_updatable | is_insertable_into -------------+--------------+-------------------- - rw_view2 | YES | YES -(1 row) - -SELECT table_name, column_name, is_updatable - FROM information_schema.columns - WHERE table_name = 'rw_view2' - ORDER BY ordinal_position; - table_name | column_name | is_updatable -------------+-------------+-------------- - rw_view2 | person | YES -(1 row) - -SELECT * FROM rw_view2 WHERE snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -NOTICE: snooped value: Harry - person --------- - Tom - Harry -(2 rows) - -UPDATE rw_view2 SET person=person WHERE snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -NOTICE: snooped value: Harry -DELETE FROM rw_view2 WHERE NOT snoop(person); -NOTICE: snooped value: Tom -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -NOTICE: snooped value: Harry -MERGE INTO rw_view2 t - USING (VALUES ('Tom'), ('Dick'), ('Harry')) AS v(person) ON t.person = v.person - WHEN MATCHED AND snoop(t.person) THEN UPDATE SET person = v.person; -NOTICE: snooped value: Tom -NOTICE: snooped value: Tom -NOTICE: snooped value: Harry -NOTICE: snooped value: Harry -EXPLAIN (costs off) SELECT * FROM rw_view2 WHERE snoop(person); - QUERY PLAN ------------------------------------------------------ - Subquery Scan on rw_view2 - Filter: snoop(rw_view2.person) - -> Subquery Scan on rw_view1 - Filter: snoop(rw_view1.person) - -> Seq Scan on base_tbl - Filter: (visibility = 'public'::text) -(6 rows) - -EXPLAIN (costs off) UPDATE rw_view2 SET person=person WHERE snoop(person); - QUERY PLAN -------------------------------------------------------------------------------------- - Update on base_tbl - -> Seq Scan on base_tbl - Filter: ((visibility = 'public'::text) AND snoop(person) AND snoop(person)) -(3 rows) - -EXPLAIN (costs off) DELETE FROM rw_view2 WHERE NOT snoop(person); - QUERY PLAN -------------------------------------------------------------------------------------------- - Delete on base_tbl - -> Seq Scan on base_tbl - Filter: ((visibility = 'public'::text) AND snoop(person) AND (NOT snoop(person))) -(3 rows) - -EXPLAIN (costs off) -MERGE INTO rw_view2 t - USING (VALUES ('Tom'), ('Dick'), ('Harry')) AS v(person) ON t.person = v.person - WHEN MATCHED AND snoop(t.person) THEN UPDATE SET person = v.person; - QUERY PLAN -------------------------------------------------------------------------- - Merge on base_tbl - -> Nested Loop - Join Filter: (base_tbl.person = "*VALUES*".column1) - -> Seq Scan on base_tbl - Filter: ((visibility = 'public'::text) AND snoop(person)) - -> Values Scan on "*VALUES*" -(6 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to 2 other objects -DETAIL: drop cascades to view rw_view1 -drop cascades to view rw_view2 --- security barrier view on top of table with rules -CREATE TABLE base_tbl(id int PRIMARY KEY, data text, deleted boolean); -INSERT INTO base_tbl VALUES (1, 'Row 1', false), (2, 'Row 2', true); -CREATE RULE base_tbl_ins_rule AS ON INSERT TO base_tbl - WHERE EXISTS (SELECT 1 FROM base_tbl t WHERE t.id = new.id) - DO INSTEAD - UPDATE base_tbl SET data = new.data, deleted = false WHERE id = new.id; -CREATE RULE base_tbl_del_rule AS ON DELETE TO base_tbl - DO INSTEAD - UPDATE base_tbl SET deleted = true WHERE id = old.id; -CREATE VIEW rw_view1 WITH (security_barrier=true) AS - SELECT id, data FROM base_tbl WHERE NOT deleted; -SELECT * FROM rw_view1; - id | data -----+------- - 1 | Row 1 -(1 row) - -EXPLAIN (costs off) DELETE FROM rw_view1 WHERE id = 1 AND snoop(data); - QUERY PLAN -------------------------------------------------------------------- - Update on base_tbl base_tbl_1 - -> Nested Loop - -> Index Scan using base_tbl_pkey on base_tbl base_tbl_1 - Index Cond: (id = 1) - -> Index Scan using base_tbl_pkey on base_tbl - Index Cond: (id = 1) - Filter: ((NOT deleted) AND snoop(data)) -(7 rows) - -DELETE FROM rw_view1 WHERE id = 1 AND snoop(data); -NOTICE: snooped value: Row 1 -EXPLAIN (costs off) INSERT INTO rw_view1 VALUES (2, 'New row 2'); - QUERY PLAN ------------------------------------------------------------ - Insert on base_tbl - InitPlan 1 - -> Index Only Scan using base_tbl_pkey on base_tbl t - Index Cond: (id = 2) - -> Result - One-Time Filter: ((InitPlan 1).col1 IS NOT TRUE) - - Update on base_tbl - InitPlan 1 - -> Index Only Scan using base_tbl_pkey on base_tbl t - Index Cond: (id = 2) - -> Result - One-Time Filter: (InitPlan 1).col1 - -> Index Scan using base_tbl_pkey on base_tbl - Index Cond: (id = 2) -(15 rows) - -INSERT INTO rw_view1 VALUES (2, 'New row 2'); -SELECT * FROM base_tbl; - id | data | deleted -----+-----------+--------- - 1 | Row 1 | t - 2 | New row 2 | f -(2 rows) - -DROP TABLE base_tbl CASCADE; -NOTICE: drop cascades to view rw_view1 --- security barrier view based on inheritance set -CREATE TABLE t1 (a int, b float, c text); -CREATE INDEX t1_a_idx ON t1(a); -INSERT INTO t1 -SELECT i,i,'t1' FROM generate_series(1,10) g(i); -ANALYZE t1; -CREATE TABLE t11 (d text) INHERITS (t1); -CREATE INDEX t11_a_idx ON t11(a); -INSERT INTO t11 -SELECT i,i,'t11','t11d' FROM generate_series(1,10) g(i); -ANALYZE t11; -CREATE TABLE t12 (e int[]) INHERITS (t1); -CREATE INDEX t12_a_idx ON t12(a); -INSERT INTO t12 -SELECT i,i,'t12','{1,2}'::int[] FROM generate_series(1,10) g(i); -ANALYZE t12; -CREATE TABLE t111 () INHERITS (t11, t12); -NOTICE: merging multiple inherited definitions of column "a" -NOTICE: merging multiple inherited definitions of column "b" -NOTICE: merging multiple inherited definitions of column "c" -CREATE INDEX t111_a_idx ON t111(a); -INSERT INTO t111 -SELECT i,i,'t111','t111d','{1,1,1}'::int[] FROM generate_series(1,10) g(i); -ANALYZE t111; -CREATE VIEW v1 WITH (security_barrier=true) AS -SELECT *, (SELECT d FROM t11 WHERE t11.a = t1.a LIMIT 1) AS d -FROM t1 -WHERE a > 5 AND EXISTS(SELECT 1 FROM t12 WHERE t12.a = t1.a); -SELECT * FROM v1 WHERE a=3; -- should not see anything - a | b | c | d ----+---+---+--- -(0 rows) - -SELECT * FROM v1 WHERE a=8; - a | b | c | d ----+---+------+------ - 8 | 8 | t1 | t11d - 8 | 8 | t11 | t11d - 8 | 8 | t12 | t11d - 8 | 8 | t111 | t11d -(4 rows) - -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6; - QUERY PLAN ------------------------------------------------------------------------------------------------------------ - Update on public.t1 - Update on public.t1 t1_1 - Update on public.t11 t1_2 - Update on public.t12 t1_3 - Update on public.t111 t1_4 - -> Result - Output: 100, t1.tableoid, t1.ctid - -> Append - -> Index Scan using t1_a_idx on public.t1 t1_1 - Output: t1_1.tableoid, t1_1.ctid - Index Cond: ((t1_1.a > 5) AND (t1_1.a < 7)) - Filter: ((t1_1.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a)) - SubPlan 1 - -> Append - -> Seq Scan on public.t12 t12_1 - Filter: (t12_1.a = t1_1.a) - -> Seq Scan on public.t111 t12_2 - Filter: (t12_2.a = t1_1.a) - -> Index Scan using t11_a_idx on public.t11 t1_2 - Output: t1_2.tableoid, t1_2.ctid - Index Cond: ((t1_2.a > 5) AND (t1_2.a < 7)) - Filter: ((t1_2.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a)) - -> Index Scan using t12_a_idx on public.t12 t1_3 - Output: t1_3.tableoid, t1_3.ctid - Index Cond: ((t1_3.a > 5) AND (t1_3.a < 7)) - Filter: ((t1_3.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a)) - -> Index Scan using t111_a_idx on public.t111 t1_4 - Output: t1_4.tableoid, t1_4.ctid - Index Cond: ((t1_4.a > 5) AND (t1_4.a < 7)) - Filter: ((t1_4.a <> 6) AND EXISTS(SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a)) -(30 rows) - -UPDATE v1 SET a=100 WHERE snoop(a) AND leakproof(a) AND a < 7 AND a != 6; -SELECT * FROM v1 WHERE a=100; -- Nothing should have been changed to 100 - a | b | c | d ----+---+---+--- -(0 rows) - -SELECT * FROM t1 WHERE a=100; -- Nothing should have been changed to 100 - a | b | c ----+---+--- -(0 rows) - -EXPLAIN (VERBOSE, COSTS OFF) -UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8; - QUERY PLAN ------------------------------------------------------------------------------------------ - Update on public.t1 - Update on public.t1 t1_1 - Update on public.t11 t1_2 - Update on public.t12 t1_3 - Update on public.t111 t1_4 - -> Result - Output: (t1.a + 1), t1.tableoid, t1.ctid - -> Append - -> Index Scan using t1_a_idx on public.t1 t1_1 - Output: t1_1.a, t1_1.tableoid, t1_1.ctid - Index Cond: ((t1_1.a > 5) AND (t1_1.a = 8)) - Filter: (EXISTS(SubPlan 1) AND snoop(t1_1.a) AND leakproof(t1_1.a)) - SubPlan 1 - -> Append - -> Seq Scan on public.t12 t12_1 - Filter: (t12_1.a = t1_1.a) - -> Seq Scan on public.t111 t12_2 - Filter: (t12_2.a = t1_1.a) - -> Index Scan using t11_a_idx on public.t11 t1_2 - Output: t1_2.a, t1_2.tableoid, t1_2.ctid - Index Cond: ((t1_2.a > 5) AND (t1_2.a = 8)) - Filter: (EXISTS(SubPlan 1) AND snoop(t1_2.a) AND leakproof(t1_2.a)) - -> Index Scan using t12_a_idx on public.t12 t1_3 - Output: t1_3.a, t1_3.tableoid, t1_3.ctid - Index Cond: ((t1_3.a > 5) AND (t1_3.a = 8)) - Filter: (EXISTS(SubPlan 1) AND snoop(t1_3.a) AND leakproof(t1_3.a)) - -> Index Scan using t111_a_idx on public.t111 t1_4 - Output: t1_4.a, t1_4.tableoid, t1_4.ctid - Index Cond: ((t1_4.a > 5) AND (t1_4.a = 8)) - Filter: (EXISTS(SubPlan 1) AND snoop(t1_4.a) AND leakproof(t1_4.a)) -(30 rows) - -UPDATE v1 SET a=a+1 WHERE snoop(a) AND leakproof(a) AND a = 8; -NOTICE: snooped value: 8 -NOTICE: snooped value: 8 -NOTICE: snooped value: 8 -NOTICE: snooped value: 8 -SELECT * FROM v1 WHERE b=8; - a | b | c | d ----+---+------+------ - 9 | 8 | t1 | t11d - 9 | 8 | t11 | t11d - 9 | 8 | t12 | t11d - 9 | 8 | t111 | t11d -(4 rows) - -DELETE FROM v1 WHERE snoop(a) AND leakproof(a); -- should not delete everything, just where a>5 -NOTICE: snooped value: 6 -NOTICE: snooped value: 7 -NOTICE: snooped value: 9 -NOTICE: snooped value: 10 -NOTICE: snooped value: 9 -NOTICE: snooped value: 6 -NOTICE: snooped value: 7 -NOTICE: snooped value: 9 -NOTICE: snooped value: 10 -NOTICE: snooped value: 9 -NOTICE: snooped value: 6 -NOTICE: snooped value: 7 -NOTICE: snooped value: 9 -NOTICE: snooped value: 10 -NOTICE: snooped value: 9 -NOTICE: snooped value: 6 -NOTICE: snooped value: 7 -NOTICE: snooped value: 9 -NOTICE: snooped value: 10 -NOTICE: snooped value: 9 -TABLE t1; -- verify all a<=5 are intact - a | b | c ----+---+------ - 1 | 1 | t1 - 2 | 2 | t1 - 3 | 3 | t1 - 4 | 4 | t1 - 5 | 5 | t1 - 1 | 1 | t11 - 2 | 2 | t11 - 3 | 3 | t11 - 4 | 4 | t11 - 5 | 5 | t11 - 1 | 1 | t12 - 2 | 2 | t12 - 3 | 3 | t12 - 4 | 4 | t12 - 5 | 5 | t12 - 1 | 1 | t111 - 2 | 2 | t111 - 3 | 3 | t111 - 4 | 4 | t111 - 5 | 5 | t111 -(20 rows) - -DROP TABLE t1, t11, t12, t111 CASCADE; -NOTICE: drop cascades to view v1 -DROP FUNCTION snoop(anyelement); -DROP FUNCTION leakproof(anyelement); -CREATE TABLE tx1 (a integer); -CREATE TABLE tx2 (b integer); -CREATE TABLE tx3 (c integer); -CREATE VIEW vx1 AS SELECT a FROM tx1 WHERE EXISTS(SELECT 1 FROM tx2 JOIN tx3 ON b=c); -INSERT INTO vx1 values (1); -SELECT * FROM tx1; - a ---- - 1 -(1 row) - -SELECT * FROM vx1; - a ---- -(0 rows) - -DROP VIEW vx1; -DROP TABLE tx1; -DROP TABLE tx2; -DROP TABLE tx3; -CREATE TABLE tx1 (a integer); -CREATE TABLE tx2 (b integer); -CREATE TABLE tx3 (c integer); -CREATE VIEW vx1 AS SELECT a FROM tx1 WHERE EXISTS(SELECT 1 FROM tx2 JOIN tx3 ON b=c); -INSERT INTO vx1 VALUES (1); -INSERT INTO vx1 VALUES (1); -SELECT * FROM tx1; - a ---- - 1 - 1 -(2 rows) - -SELECT * FROM vx1; - a ---- -(0 rows) - -DROP VIEW vx1; -DROP TABLE tx1; -DROP TABLE tx2; -DROP TABLE tx3; -CREATE TABLE tx1 (a integer, b integer); -CREATE TABLE tx2 (b integer, c integer); -CREATE TABLE tx3 (c integer, d integer); -ALTER TABLE tx1 DROP COLUMN b; -ALTER TABLE tx2 DROP COLUMN c; -ALTER TABLE tx3 DROP COLUMN d; -CREATE VIEW vx1 AS SELECT a FROM tx1 WHERE EXISTS(SELECT 1 FROM tx2 JOIN tx3 ON b=c); -INSERT INTO vx1 VALUES (1); -INSERT INTO vx1 VALUES (1); -SELECT * FROM tx1; - a ---- - 1 - 1 -(2 rows) - -SELECT * FROM vx1; - a ---- -(0 rows) - -DROP VIEW vx1; -DROP TABLE tx1; -DROP TABLE tx2; -DROP TABLE tx3; --- --- Test handling of vars from correlated subqueries in quals from outer --- security barrier views, per bug #13988 --- -CREATE TABLE t1 (a int, b text, c int); -INSERT INTO t1 VALUES (1, 'one', 10); -CREATE TABLE t2 (cc int); -INSERT INTO t2 VALUES (10), (20); -CREATE VIEW v1 WITH (security_barrier = true) AS - SELECT * FROM t1 WHERE (a > 0) - WITH CHECK OPTION; -CREATE VIEW v2 WITH (security_barrier = true) AS - SELECT * FROM v1 WHERE EXISTS (SELECT 1 FROM t2 WHERE t2.cc = v1.c) - WITH CHECK OPTION; -INSERT INTO v2 VALUES (2, 'two', 20); -- ok -INSERT INTO v2 VALUES (-2, 'minus two', 20); -- not allowed -ERROR: new row violates check option for view "v1" -DETAIL: Failing row contains (-2, minus two, 20). -INSERT INTO v2 VALUES (3, 'three', 30); -- not allowed -ERROR: new row violates check option for view "v2" -DETAIL: Failing row contains (3, three, 30). -UPDATE v2 SET b = 'ONE' WHERE a = 1; -- ok -UPDATE v2 SET a = -1 WHERE a = 1; -- not allowed -ERROR: new row violates check option for view "v1" -DETAIL: Failing row contains (-1, ONE, 10). -UPDATE v2 SET c = 30 WHERE a = 1; -- not allowed -ERROR: new row violates check option for view "v2" -DETAIL: Failing row contains (1, ONE, 30). -DELETE FROM v2 WHERE a = 2; -- ok -SELECT * FROM v2; - a | b | c ----+-----+---- - 1 | ONE | 10 -(1 row) - -DROP VIEW v2; -DROP VIEW v1; -DROP TABLE t2; -DROP TABLE t1; --- --- Test sub-select in nested security barrier views, per bug #17972 --- -CREATE TABLE t1 (a int); -CREATE VIEW v1 WITH (security_barrier = true) AS - SELECT * FROM t1; -CREATE RULE v1_upd_rule AS ON UPDATE TO v1 DO INSTEAD - UPDATE t1 SET a = NEW.a WHERE a = OLD.a; -CREATE VIEW v2 WITH (security_barrier = true) AS - SELECT * FROM v1 WHERE EXISTS (SELECT 1); -EXPLAIN (COSTS OFF) UPDATE v2 SET a = 1; - QUERY PLAN --------------------------------------------------------------- - Update on t1 - InitPlan 1 - -> Result - -> Merge Join - Merge Cond: (t1.a = v1.a) - -> Sort - Sort Key: t1.a - -> Seq Scan on t1 - -> Sort - Sort Key: v1.a - -> Subquery Scan on v1 - -> Result - One-Time Filter: (InitPlan 1).col1 - -> Seq Scan on t1 t1_1 -(14 rows) - -DROP VIEW v2; -DROP VIEW v1; -DROP TABLE t1; --- --- Test CREATE OR REPLACE VIEW turning a non-updatable view into an --- auto-updatable view and adding check options in a single step --- -CREATE TABLE t1 (a int, b text); -CREATE VIEW v1 AS SELECT null::int AS a; -CREATE OR REPLACE VIEW v1 AS SELECT * FROM t1 WHERE a > 0 WITH CHECK OPTION; -INSERT INTO v1 VALUES (1, 'ok'); -- ok -INSERT INTO v1 VALUES (-1, 'invalid'); -- should fail -ERROR: new row violates check option for view "v1" -DETAIL: Failing row contains (-1, invalid). -DROP VIEW v1; -DROP TABLE t1; --- check that an auto-updatable view on a partitioned table works correctly -create table uv_pt (a int, b int, v varchar) partition by range (a, b); -create table uv_pt1 (b int not null, v varchar, a int not null) partition by range (b); -create table uv_pt11 (like uv_pt1); -alter table uv_pt11 drop a; -alter table uv_pt11 add a int; -alter table uv_pt11 drop a; -alter table uv_pt11 add a int not null; -alter table uv_pt1 attach partition uv_pt11 for values from (2) to (5); -alter table uv_pt attach partition uv_pt1 for values from (1, 2) to (1, 10); -create view uv_ptv as select * from uv_pt; -select events & 4 != 0 AS upd, - events & 8 != 0 AS ins, - events & 16 != 0 AS del - from pg_catalog.pg_relation_is_updatable('uv_pt'::regclass, false) t(events); - upd | ins | del ------+-----+----- - t | t | t -(1 row) - -select pg_catalog.pg_column_is_updatable('uv_pt'::regclass, 1::smallint, false); - pg_column_is_updatable ------------------------- - t -(1 row) - -select pg_catalog.pg_column_is_updatable('uv_pt'::regclass, 2::smallint, false); - pg_column_is_updatable ------------------------- - t -(1 row) - -select table_name, is_updatable, is_insertable_into - from information_schema.views where table_name = 'uv_ptv'; - table_name | is_updatable | is_insertable_into -------------+--------------+-------------------- - uv_ptv | YES | YES -(1 row) - -select table_name, column_name, is_updatable - from information_schema.columns where table_name = 'uv_ptv' order by column_name; - table_name | column_name | is_updatable -------------+-------------+-------------- - uv_ptv | a | YES - uv_ptv | b | YES - uv_ptv | v | YES -(3 rows) - -insert into uv_ptv values (1, 2); -select tableoid::regclass, * from uv_pt; - tableoid | a | b | v -----------+---+---+--- - uv_pt11 | 1 | 2 | -(1 row) - -create view uv_ptv_wco as select * from uv_pt where a = 0 with check option; -insert into uv_ptv_wco values (1, 2); -ERROR: new row violates check option for view "uv_ptv_wco" -DETAIL: Failing row contains (1, 2, null). -merge into uv_ptv t - using (values (1,2), (1,4)) as v(a,b) on t.a = v.a -- fail: matches 2 src rows - when matched then update set b = t.b + 1 - when not matched then insert values (v.a, v.b + 1); -ERROR: MERGE command cannot affect row a second time -HINT: Ensure that not more than one source row matches any one target row. -merge into uv_ptv t - using (values (1,2), (1,4)) as v(a,b) on t.a = v.a and t.b = v.b - when matched then update set b = t.b + 1 - when not matched then insert values (v.a, v.b + 1); -- fail: no partition for b=5 -ERROR: no partition of relation "uv_pt1" found for row -DETAIL: Partition key of the failing row contains (b) = (5). -merge into uv_ptv t - using (values (1,2), (1,3)) as v(a,b) on t.a = v.a and t.b = v.b - when matched then update set b = t.b + 1 - when not matched then insert values (v.a, v.b + 1); -- ok -select tableoid::regclass, * from uv_pt order by a, b; - tableoid | a | b | v -----------+---+---+--- - uv_pt11 | 1 | 3 | - uv_pt11 | 1 | 4 | -(2 rows) - -drop view uv_ptv, uv_ptv_wco; -drop table uv_pt, uv_pt1, uv_pt11; --- check that wholerow vars appearing in WITH CHECK OPTION constraint expressions --- work fine with partitioned tables -create table wcowrtest (a int) partition by list (a); -create table wcowrtest1 partition of wcowrtest for values in (1); -create view wcowrtest_v as select * from wcowrtest where wcowrtest = '(2)'::wcowrtest with check option; -insert into wcowrtest_v values (1); -ERROR: new row violates check option for view "wcowrtest_v" -DETAIL: Failing row contains (1). -alter table wcowrtest add b text; -create table wcowrtest2 (b text, c int, a int); -alter table wcowrtest2 drop c; -alter table wcowrtest attach partition wcowrtest2 for values in (2); -create table sometable (a int, b text); -insert into sometable values (1, 'a'), (2, 'b'); -create view wcowrtest_v2 as - select * - from wcowrtest r - where r in (select s from sometable s where r.a = s.a) -with check option; --- WITH CHECK qual will be processed with wcowrtest2's --- rowtype after tuple-routing -insert into wcowrtest_v2 values (2, 'no such row in sometable'); -ERROR: new row violates check option for view "wcowrtest_v2" -DETAIL: Failing row contains (2, no such row in sometable). -drop view wcowrtest_v, wcowrtest_v2; -drop table wcowrtest, sometable; --- Check INSERT .. ON CONFLICT DO UPDATE works correctly when the view's --- columns are named and ordered differently than the underlying table's. -create table uv_iocu_tab (a text unique, b float); -insert into uv_iocu_tab values ('xyxyxy', 0); -create view uv_iocu_view as - select b, b+1 as c, a, '2.0'::text as two from uv_iocu_tab; -insert into uv_iocu_view (a, b) values ('xyxyxy', 1) - on conflict (a) do update set b = uv_iocu_view.b; -select * from uv_iocu_tab; - a | b ---------+--- - xyxyxy | 0 -(1 row) - -insert into uv_iocu_view (a, b) values ('xyxyxy', 1) - on conflict (a) do update set b = excluded.b; -select * from uv_iocu_tab; - a | b ---------+--- - xyxyxy | 1 -(1 row) - --- OK to access view columns that are not present in underlying base --- relation in the ON CONFLICT portion of the query -insert into uv_iocu_view (a, b) values ('xyxyxy', 3) - on conflict (a) do update set b = cast(excluded.two as float); -select * from uv_iocu_tab; - a | b ---------+--- - xyxyxy | 2 -(1 row) - -explain (costs off) -insert into uv_iocu_view (a, b) values ('xyxyxy', 3) - on conflict (a) do update set b = excluded.b where excluded.c > 0; - QUERY PLAN ------------------------------------------------------------------------------------ - Insert on uv_iocu_tab - Conflict Resolution: UPDATE - Conflict Arbiter Indexes: uv_iocu_tab_a_key - Conflict Filter: ((excluded.b + '1'::double precision) > '0'::double precision) - -> Result -(5 rows) - -insert into uv_iocu_view (a, b) values ('xyxyxy', 3) - on conflict (a) do update set b = excluded.b where excluded.c > 0; -select * from uv_iocu_tab; - a | b ---------+--- - xyxyxy | 3 -(1 row) - -drop view uv_iocu_view; -drop table uv_iocu_tab; --- Test whole-row references to the view -create table uv_iocu_tab (a int unique, b text); -create view uv_iocu_view as - select b as bb, a as aa, uv_iocu_tab::text as cc from uv_iocu_tab; -insert into uv_iocu_view (aa,bb) values (1,'x'); -explain (costs off) -insert into uv_iocu_view (aa,bb) values (1,'y') - on conflict (aa) do update set bb = 'Rejected: '||excluded.* - where excluded.aa > 0 - and excluded.bb != '' - and excluded.cc is not null; - QUERY PLAN ---------------------------------------------------------------------------------------------------------- - Insert on uv_iocu_tab - Conflict Resolution: UPDATE - Conflict Arbiter Indexes: uv_iocu_tab_a_key - Conflict Filter: ((excluded.a > 0) AND (excluded.b <> ''::text) AND ((excluded.*)::text IS NOT NULL)) - -> Result -(5 rows) - -insert into uv_iocu_view (aa,bb) values (1,'y') - on conflict (aa) do update set bb = 'Rejected: '||excluded.* - where excluded.aa > 0 - and excluded.bb != '' - and excluded.cc is not null; -select * from uv_iocu_view; - bb | aa | cc --------------------------+----+--------------------------------- - Rejected: (y,1,"(1,y)") | 1 | (1,"Rejected: (y,1,""(1,y)"")") -(1 row) - --- Test omitting a column of the base relation -delete from uv_iocu_view; -insert into uv_iocu_view (aa,bb) values (1,'x'); -insert into uv_iocu_view (aa) values (1) - on conflict (aa) do update set bb = 'Rejected: '||excluded.*; -select * from uv_iocu_view; - bb | aa | cc ------------------------+----+------------------------------- - Rejected: (,1,"(1,)") | 1 | (1,"Rejected: (,1,""(1,)"")") -(1 row) - -alter table uv_iocu_tab alter column b set default 'table default'; -insert into uv_iocu_view (aa) values (1) - on conflict (aa) do update set bb = 'Rejected: '||excluded.*; -select * from uv_iocu_view; - bb | aa | cc --------------------------------------------------------+----+--------------------------------------------------------------------- - Rejected: ("table default",1,"(1,""table default"")") | 1 | (1,"Rejected: (""table default"",1,""(1,""""table default"""")"")") -(1 row) - -alter view uv_iocu_view alter column bb set default 'view default'; -insert into uv_iocu_view (aa) values (1) - on conflict (aa) do update set bb = 'Rejected: '||excluded.*; -select * from uv_iocu_view; - bb | aa | cc ------------------------------------------------------+----+------------------------------------------------------------------- - Rejected: ("view default",1,"(1,""view default"")") | 1 | (1,"Rejected: (""view default"",1,""(1,""""view default"""")"")") -(1 row) - --- Should fail to update non-updatable columns -insert into uv_iocu_view (aa) values (1) - on conflict (aa) do update set cc = 'XXX'; -ERROR: cannot insert into column "cc" of view "uv_iocu_view" -DETAIL: View columns that are not columns of their base relation are not updatable. -drop view uv_iocu_view; -drop table uv_iocu_tab; --- ON CONFLICT DO UPDATE permissions checks -create user regress_view_user1; -create user regress_view_user2; -set session authorization regress_view_user1; -create table base_tbl(a int unique, b text, c float); -insert into base_tbl values (1,'xxx',1.0); -create view rw_view1 as select b as bb, c as cc, a as aa from base_tbl; -grant select (aa,bb) on rw_view1 to regress_view_user2; -grant insert on rw_view1 to regress_view_user2; -grant update (bb) on rw_view1 to regress_view_user2; -set session authorization regress_view_user2; -insert into rw_view1 values ('yyy',2.0,1) - on conflict (aa) do update set bb = excluded.cc; -- Not allowed -ERROR: permission denied for view rw_view1 -insert into rw_view1 values ('yyy',2.0,1) - on conflict (aa) do update set bb = rw_view1.cc; -- Not allowed -ERROR: permission denied for view rw_view1 -insert into rw_view1 values ('yyy',2.0,1) - on conflict (aa) do update set bb = excluded.bb; -- OK -insert into rw_view1 values ('zzz',2.0,1) - on conflict (aa) do update set bb = rw_view1.bb||'xxx'; -- OK -insert into rw_view1 values ('zzz',2.0,1) - on conflict (aa) do update set cc = 3.0; -- Not allowed -ERROR: permission denied for view rw_view1 -reset session authorization; -select * from base_tbl; - a | b | c ----+--------+--- - 1 | yyyxxx | 1 -(1 row) - -set session authorization regress_view_user1; -grant select (a,b) on base_tbl to regress_view_user2; -grant insert (a,b) on base_tbl to regress_view_user2; -grant update (a,b) on base_tbl to regress_view_user2; -set session authorization regress_view_user2; -create view rw_view2 as select b as bb, c as cc, a as aa from base_tbl; -insert into rw_view2 (aa,bb) values (1,'xxx') - on conflict (aa) do update set bb = excluded.bb; -- Not allowed -ERROR: permission denied for table base_tbl -create view rw_view3 as select b as bb, a as aa from base_tbl; -insert into rw_view3 (aa,bb) values (1,'xxx') - on conflict (aa) do update set bb = excluded.bb; -- OK -reset session authorization; -select * from base_tbl; - a | b | c ----+-----+--- - 1 | xxx | 1 -(1 row) - -set session authorization regress_view_user2; -create view rw_view4 as select aa, bb, cc FROM rw_view1; -insert into rw_view4 (aa,bb) values (1,'yyy') - on conflict (aa) do update set bb = excluded.bb; -- Not allowed -ERROR: permission denied for view rw_view1 -create view rw_view5 as select aa, bb FROM rw_view1; -insert into rw_view5 (aa,bb) values (1,'yyy') - on conflict (aa) do update set bb = excluded.bb; -- OK -reset session authorization; -select * from base_tbl; - a | b | c ----+-----+--- - 1 | yyy | 1 -(1 row) - -drop view rw_view5; -drop view rw_view4; -drop view rw_view3; -drop view rw_view2; -drop view rw_view1; -drop table base_tbl; -drop user regress_view_user1; -drop user regress_view_user2; --- Test single- and multi-row inserts with table and view defaults. --- Table defaults should be used, unless overridden by view defaults. -create table base_tab_def (a int, b text default 'Table default', - c text default 'Table default', d text, e text); -create view base_tab_def_view as select * from base_tab_def; -alter view base_tab_def_view alter b set default 'View default'; -alter view base_tab_def_view alter d set default 'View default'; -insert into base_tab_def values (1); -insert into base_tab_def values (2), (3); -insert into base_tab_def values (4, default, default, default, default); -insert into base_tab_def values (5, default, default, default, default), - (6, default, default, default, default); -insert into base_tab_def_view values (11); -insert into base_tab_def_view values (12), (13); -insert into base_tab_def_view values (14, default, default, default, default); -insert into base_tab_def_view values (15, default, default, default, default), - (16, default, default, default, default); -insert into base_tab_def_view values (17), (default); -select * from base_tab_def order by a; - a | b | c | d | e -----+---------------+---------------+--------------+--- - 1 | Table default | Table default | | - 2 | Table default | Table default | | - 3 | Table default | Table default | | - 4 | Table default | Table default | | - 5 | Table default | Table default | | - 6 | Table default | Table default | | - 11 | View default | Table default | View default | - 12 | View default | Table default | View default | - 13 | View default | Table default | View default | - 14 | View default | Table default | View default | - 15 | View default | Table default | View default | - 16 | View default | Table default | View default | - 17 | View default | Table default | View default | - | View default | Table default | View default | -(14 rows) - --- Adding an INSTEAD OF trigger should cause NULLs to be inserted instead of --- table defaults, where there are no view defaults. -create function base_tab_def_view_instrig_func() returns trigger -as -$$ -begin - insert into base_tab_def values (new.a, new.b, new.c, new.d, new.e); - return new; -end; -$$ -language plpgsql; -create trigger base_tab_def_view_instrig instead of insert on base_tab_def_view - for each row execute function base_tab_def_view_instrig_func(); -truncate base_tab_def; -insert into base_tab_def values (1); -insert into base_tab_def values (2), (3); -insert into base_tab_def values (4, default, default, default, default); -insert into base_tab_def values (5, default, default, default, default), - (6, default, default, default, default); -insert into base_tab_def_view values (11); -insert into base_tab_def_view values (12), (13); -insert into base_tab_def_view values (14, default, default, default, default); -insert into base_tab_def_view values (15, default, default, default, default), - (16, default, default, default, default); -insert into base_tab_def_view values (17), (default); -select * from base_tab_def order by a; - a | b | c | d | e -----+---------------+---------------+--------------+--- - 1 | Table default | Table default | | - 2 | Table default | Table default | | - 3 | Table default | Table default | | - 4 | Table default | Table default | | - 5 | Table default | Table default | | - 6 | Table default | Table default | | - 11 | View default | | View default | - 12 | View default | | View default | - 13 | View default | | View default | - 14 | View default | | View default | - 15 | View default | | View default | - 16 | View default | | View default | - 17 | View default | | View default | - | View default | | View default | -(14 rows) - --- Using an unconditional DO INSTEAD rule should also cause NULLs to be --- inserted where there are no view defaults. -drop trigger base_tab_def_view_instrig on base_tab_def_view; -drop function base_tab_def_view_instrig_func; -create rule base_tab_def_view_ins_rule as on insert to base_tab_def_view - do instead insert into base_tab_def values (new.a, new.b, new.c, new.d, new.e); -truncate base_tab_def; -insert into base_tab_def values (1); -insert into base_tab_def values (2), (3); -insert into base_tab_def values (4, default, default, default, default); -insert into base_tab_def values (5, default, default, default, default), - (6, default, default, default, default); -insert into base_tab_def_view values (11); -insert into base_tab_def_view values (12), (13); -insert into base_tab_def_view values (14, default, default, default, default); -insert into base_tab_def_view values (15, default, default, default, default), - (16, default, default, default, default); -insert into base_tab_def_view values (17), (default); -select * from base_tab_def order by a; - a | b | c | d | e -----+---------------+---------------+--------------+--- - 1 | Table default | Table default | | - 2 | Table default | Table default | | - 3 | Table default | Table default | | - 4 | Table default | Table default | | - 5 | Table default | Table default | | - 6 | Table default | Table default | | - 11 | View default | | View default | - 12 | View default | | View default | - 13 | View default | | View default | - 14 | View default | | View default | - 15 | View default | | View default | - 16 | View default | | View default | - 17 | View default | | View default | - | View default | | View default | -(14 rows) - --- A DO ALSO rule should cause each row to be inserted twice. The first --- insert should behave the same as an auto-updatable view (using table --- defaults, unless overridden by view defaults). The second insert should --- behave the same as a rule-updatable view (inserting NULLs where there are --- no view defaults). -drop rule base_tab_def_view_ins_rule on base_tab_def_view; -create rule base_tab_def_view_ins_rule as on insert to base_tab_def_view - do also insert into base_tab_def values (new.a, new.b, new.c, new.d, new.e); -truncate base_tab_def; -insert into base_tab_def values (1); -insert into base_tab_def values (2), (3); -insert into base_tab_def values (4, default, default, default, default); -insert into base_tab_def values (5, default, default, default, default), - (6, default, default, default, default); -insert into base_tab_def_view values (11); -insert into base_tab_def_view values (12), (13); -insert into base_tab_def_view values (14, default, default, default, default); -insert into base_tab_def_view values (15, default, default, default, default), - (16, default, default, default, default); -insert into base_tab_def_view values (17), (default); -select * from base_tab_def order by a, c NULLS LAST; - a | b | c | d | e -----+---------------+---------------+--------------+--- - 1 | Table default | Table default | | - 2 | Table default | Table default | | - 3 | Table default | Table default | | - 4 | Table default | Table default | | - 5 | Table default | Table default | | - 6 | Table default | Table default | | - 11 | View default | Table default | View default | - 11 | View default | | View default | - 12 | View default | Table default | View default | - 12 | View default | | View default | - 13 | View default | Table default | View default | - 13 | View default | | View default | - 14 | View default | Table default | View default | - 14 | View default | | View default | - 15 | View default | Table default | View default | - 15 | View default | | View default | - 16 | View default | Table default | View default | - 16 | View default | | View default | - 17 | View default | Table default | View default | - 17 | View default | | View default | - | View default | Table default | View default | - | View default | | View default | -(22 rows) - --- Test a DO ALSO INSERT ... SELECT rule -drop rule base_tab_def_view_ins_rule on base_tab_def_view; -create rule base_tab_def_view_ins_rule as on insert to base_tab_def_view - do also insert into base_tab_def (a, b, e) select new.a, new.b, 'xxx'; -truncate base_tab_def; -insert into base_tab_def_view values (1, default, default, default, default); -insert into base_tab_def_view values (2, default, default, default, default), - (3, default, default, default, default); -select * from base_tab_def order by a, e nulls first; - a | b | c | d | e ----+--------------+---------------+--------------+----- - 1 | View default | Table default | View default | - 1 | View default | Table default | | xxx - 2 | View default | Table default | View default | - 2 | View default | Table default | | xxx - 3 | View default | Table default | View default | - 3 | View default | Table default | | xxx -(6 rows) - -drop view base_tab_def_view; -drop table base_tab_def; --- Test defaults with array assignments -create table base_tab (a serial, b int[], c text, d text default 'Table default'); -create view base_tab_view as select c, a, b from base_tab; -alter view base_tab_view alter column c set default 'View default'; -insert into base_tab_view (b[1], b[2], c, b[5], b[4], a, b[3]) -values (1, 2, default, 5, 4, default, 3), (10, 11, 'C value', 14, 13, 100, 12); -select * from base_tab order by a; - a | b | c | d ------+------------------+--------------+--------------- - 1 | {1,2,3,4,5} | View default | Table default - 100 | {10,11,12,13,14} | C value | Table default -(2 rows) - -drop view base_tab_view; -drop table base_tab; +server closed the connection unexpectedly + This probably means the server terminated abnormally + before or while processing the request. +connection to server was lost diff -w -U3 C:/cirrus/src/test/regress/expected/sanity_check.out C:/cirrus/build/testrun/regress/regress/results/sanity_check.out --- C:/cirrus/src/test/regress/expected/sanity_check.out 2024-03-20 22:41:28.997855300 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/sanity_check.out 2024-03-20 22:44:01.151428100 +0000 @@ -1,27 +1,2 @@ -VACUUM; --- --- Sanity check: every system catalog that has OIDs should have --- a unique index on OID. This ensures that the OIDs will be unique, --- even after the OID counter wraps around. --- We exclude non-system tables from the check by looking at nspname. --- -SELECT relname, nspname - FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = relnamespace JOIN pg_attribute a ON (attrelid = c.oid AND attname = 'oid') - WHERE relkind = 'r' and c.oid < 16384 - AND ((nspname ~ '^pg_') IS NOT FALSE) - AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE indrelid = c.oid - AND indkey[0] = a.attnum AND indnatts = 1 - AND indisunique AND indimmediate); - relname | nspname ----------+--------- -(0 rows) - --- check that relations without storage don't have relfilenode -SELECT relname, relkind - FROM pg_class - WHERE relkind IN ('v', 'c', 'f', 'p', 'I') - AND relfilenode <> 0; - relname | relkind ----------+--------- -(0 rows) - +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/select_distinct.out C:/cirrus/build/testrun/regress/regress/results/select_distinct.out --- C:/cirrus/src/test/regress/expected/select_distinct.out 2024-03-20 22:41:29.002394300 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/select_distinct.out 2024-03-20 22:44:01.621151700 +0000 @@ -1,466 +1,2 @@ --- --- SELECT_DISTINCT --- --- --- awk '{print $3;}' onek.data | sort -n | uniq --- -SELECT DISTINCT two FROM onek ORDER BY 1; - two ------ - 0 - 1 -(2 rows) - --- --- awk '{print $5;}' onek.data | sort -n | uniq --- -SELECT DISTINCT ten FROM onek ORDER BY 1; - ten ------ - 0 - 1 - 2 - 3 - 4 - 5 - 6 - 7 - 8 - 9 -(10 rows) - --- --- awk '{print $16;}' onek.data | sort -d | uniq --- -SELECT DISTINCT string4 FROM onek ORDER BY 1; - string4 ---------- - AAAAxx - HHHHxx - OOOOxx - VVVVxx -(4 rows) - --- --- awk '{print $3,$16,$5;}' onek.data | sort -d | uniq | --- sort +0n -1 +1d -2 +2n -3 --- -SELECT DISTINCT two, string4, ten - FROM onek - ORDER BY two using <, string4 using <, ten using <; - two | string4 | ten ------+---------+----- - 0 | AAAAxx | 0 - 0 | AAAAxx | 2 - 0 | AAAAxx | 4 - 0 | AAAAxx | 6 - 0 | AAAAxx | 8 - 0 | HHHHxx | 0 - 0 | HHHHxx | 2 - 0 | HHHHxx | 4 - 0 | HHHHxx | 6 - 0 | HHHHxx | 8 - 0 | OOOOxx | 0 - 0 | OOOOxx | 2 - 0 | OOOOxx | 4 - 0 | OOOOxx | 6 - 0 | OOOOxx | 8 - 0 | VVVVxx | 0 - 0 | VVVVxx | 2 - 0 | VVVVxx | 4 - 0 | VVVVxx | 6 - 0 | VVVVxx | 8 - 1 | AAAAxx | 1 - 1 | AAAAxx | 3 - 1 | AAAAxx | 5 - 1 | AAAAxx | 7 - 1 | AAAAxx | 9 - 1 | HHHHxx | 1 - 1 | HHHHxx | 3 - 1 | HHHHxx | 5 - 1 | HHHHxx | 7 - 1 | HHHHxx | 9 - 1 | OOOOxx | 1 - 1 | OOOOxx | 3 - 1 | OOOOxx | 5 - 1 | OOOOxx | 7 - 1 | OOOOxx | 9 - 1 | VVVVxx | 1 - 1 | VVVVxx | 3 - 1 | VVVVxx | 5 - 1 | VVVVxx | 7 - 1 | VVVVxx | 9 -(40 rows) - --- --- awk '{print $2;}' person.data | --- awk '{if(NF!=1){print $2;}else{print;}}' - emp.data | --- awk '{if(NF!=1){print $2;}else{print;}}' - student.data | --- awk 'BEGIN{FS=" ";}{if(NF!=1){print $5;}else{print;}}' - stud_emp.data | --- sort -n -r | uniq --- -SELECT DISTINCT p.age FROM person* p ORDER BY age using >; - age ------ - 98 - 88 - 78 - 68 - 60 - 58 - 50 - 48 - 40 - 38 - 34 - 30 - 28 - 25 - 24 - 23 - 20 - 19 - 18 - 8 -(20 rows) - --- --- Check mentioning same column more than once --- -EXPLAIN (VERBOSE, COSTS OFF) -SELECT count(*) FROM - (SELECT DISTINCT two, four, two FROM tenk1) ss; - QUERY PLAN --------------------------------------------------------- - Aggregate - Output: count(*) - -> HashAggregate - Output: tenk1.two, tenk1.four, tenk1.two - Group Key: tenk1.two, tenk1.four - -> Seq Scan on public.tenk1 - Output: tenk1.two, tenk1.four, tenk1.two -(7 rows) - -SELECT count(*) FROM - (SELECT DISTINCT two, four, two FROM tenk1) ss; - count -------- - 4 -(1 row) - --- --- Compare results between plans using sorting and plans using hash --- aggregation. Force spilling in both cases by setting work_mem low. --- -SET work_mem='64kB'; --- Produce results with sorting. -SET enable_hashagg=FALSE; -SET jit_above_cost=0; -EXPLAIN (costs off) -SELECT DISTINCT g%1000 FROM generate_series(0,9999) g; - QUERY PLAN ------------------------------------------------- - Unique - -> Sort - Sort Key: ((g % 1000)) - -> Function Scan on generate_series g -(4 rows) - -CREATE TABLE distinct_group_1 AS -SELECT DISTINCT g%1000 FROM generate_series(0,9999) g; -SET jit_above_cost TO DEFAULT; -CREATE TABLE distinct_group_2 AS -SELECT DISTINCT (g%1000)::text FROM generate_series(0,9999) g; -SET enable_seqscan = 0; --- Check to see we get an incremental sort plan -EXPLAIN (costs off) -SELECT DISTINCT hundred, two FROM tenk1; - QUERY PLAN ------------------------------------------------------ - Unique - -> Incremental Sort - Sort Key: hundred, two - Presorted Key: hundred - -> Index Scan using tenk1_hundred on tenk1 -(5 rows) - -RESET enable_seqscan; -SET enable_hashagg=TRUE; --- Produce results with hash aggregation. -SET enable_sort=FALSE; -SET jit_above_cost=0; -EXPLAIN (costs off) -SELECT DISTINCT g%1000 FROM generate_series(0,9999) g; - QUERY PLAN ------------------------------------------- - HashAggregate - Group Key: (g % 1000) - -> Function Scan on generate_series g -(3 rows) - -CREATE TABLE distinct_hash_1 AS -SELECT DISTINCT g%1000 FROM generate_series(0,9999) g; -SET jit_above_cost TO DEFAULT; -CREATE TABLE distinct_hash_2 AS -SELECT DISTINCT (g%1000)::text FROM generate_series(0,9999) g; -SET enable_sort=TRUE; -SET work_mem TO DEFAULT; --- Compare results -(SELECT * FROM distinct_hash_1 EXCEPT SELECT * FROM distinct_group_1) - UNION ALL -(SELECT * FROM distinct_group_1 EXCEPT SELECT * FROM distinct_hash_1); - ?column? ----------- -(0 rows) - -(SELECT * FROM distinct_hash_1 EXCEPT SELECT * FROM distinct_group_1) - UNION ALL -(SELECT * FROM distinct_group_1 EXCEPT SELECT * FROM distinct_hash_1); - ?column? ----------- -(0 rows) - -DROP TABLE distinct_hash_1; -DROP TABLE distinct_hash_2; -DROP TABLE distinct_group_1; -DROP TABLE distinct_group_2; --- Test parallel DISTINCT -SET parallel_tuple_cost=0; -SET parallel_setup_cost=0; -SET min_parallel_table_scan_size=0; -SET max_parallel_workers_per_gather=2; --- Ensure we get a parallel plan -EXPLAIN (costs off) -SELECT DISTINCT four FROM tenk1; - QUERY PLAN ----------------------------------------------------- - Unique - -> Gather Merge - Workers Planned: 2 - -> Sort - Sort Key: four - -> HashAggregate - Group Key: four - -> Parallel Seq Scan on tenk1 -(8 rows) - --- Ensure the parallel plan produces the correct results -SELECT DISTINCT four FROM tenk1; - four ------- - 0 - 1 - 2 - 3 -(4 rows) - -CREATE OR REPLACE FUNCTION distinct_func(a INT) RETURNS INT AS $$ - BEGIN - RETURN a; - END; -$$ LANGUAGE plpgsql PARALLEL UNSAFE; --- Ensure we don't do parallel distinct with a parallel unsafe function -EXPLAIN (COSTS OFF) -SELECT DISTINCT distinct_func(1) FROM tenk1; - QUERY PLAN ----------------------------------------------------------- - Unique - -> Sort - Sort Key: (distinct_func(1)) - -> Index Only Scan using tenk1_hundred on tenk1 -(4 rows) - --- make the function parallel safe -CREATE OR REPLACE FUNCTION distinct_func(a INT) RETURNS INT AS $$ - BEGIN - RETURN a; - END; -$$ LANGUAGE plpgsql PARALLEL SAFE; --- Ensure we do parallel distinct now that the function is parallel safe -EXPLAIN (COSTS OFF) -SELECT DISTINCT distinct_func(1) FROM tenk1; - QUERY PLAN ----------------------------------------------------- - Unique - -> Gather Merge - Workers Planned: 2 - -> Unique - -> Sort - Sort Key: (distinct_func(1)) - -> Parallel Seq Scan on tenk1 -(7 rows) - -RESET max_parallel_workers_per_gather; -RESET min_parallel_table_scan_size; -RESET parallel_setup_cost; -RESET parallel_tuple_cost; --- --- Test the planner's ability to use a LIMIT 1 instead of a Unique node when --- all of the distinct_pathkeys have been marked as redundant --- --- Ensure we get a plan with a Limit 1 -EXPLAIN (COSTS OFF) -SELECT DISTINCT four FROM tenk1 WHERE four = 0; - QUERY PLAN ----------------------------- - Limit - -> Seq Scan on tenk1 - Filter: (four = 0) -(3 rows) - --- Ensure the above gives us the correct result -SELECT DISTINCT four FROM tenk1 WHERE four = 0; - four ------- - 0 -(1 row) - --- Ensure we get a plan with a Limit 1 -EXPLAIN (COSTS OFF) -SELECT DISTINCT four FROM tenk1 WHERE four = 0 AND two <> 0; - QUERY PLAN ---------------------------------------------- - Limit - -> Seq Scan on tenk1 - Filter: ((two <> 0) AND (four = 0)) -(3 rows) - --- Ensure no rows are returned -SELECT DISTINCT four FROM tenk1 WHERE four = 0 AND two <> 0; - four ------- -(0 rows) - --- Ensure we get a plan with a Limit 1 when the SELECT list contains constants -EXPLAIN (COSTS OFF) -SELECT DISTINCT four,1,2,3 FROM tenk1 WHERE four = 0; - QUERY PLAN ----------------------------- - Limit - -> Seq Scan on tenk1 - Filter: (four = 0) -(3 rows) - --- Ensure we only get 1 row -SELECT DISTINCT four,1,2,3 FROM tenk1 WHERE four = 0; - four | ?column? | ?column? | ?column? -------+----------+----------+---------- - 0 | 1 | 2 | 3 -(1 row) - -SET parallel_setup_cost=0; -SET min_parallel_table_scan_size=0; -SET max_parallel_workers_per_gather=2; --- Ensure we get a plan with a Limit 1 in both partial distinct and final --- distinct -EXPLAIN (COSTS OFF) -SELECT DISTINCT four FROM tenk1 WHERE four = 10; - QUERY PLAN ----------------------------------------------- - Limit - -> Gather - Workers Planned: 2 - -> Limit - -> Parallel Seq Scan on tenk1 - Filter: (four = 10) -(6 rows) - -RESET max_parallel_workers_per_gather; -RESET min_parallel_table_scan_size; -RESET parallel_setup_cost; --- --- Also, some tests of IS DISTINCT FROM, which doesn't quite deserve its --- very own regression file. --- -CREATE TEMP TABLE disttable (f1 integer); -INSERT INTO DISTTABLE VALUES(1); -INSERT INTO DISTTABLE VALUES(2); -INSERT INTO DISTTABLE VALUES(3); -INSERT INTO DISTTABLE VALUES(NULL); --- basic cases -SELECT f1, f1 IS DISTINCT FROM 2 as "not 2" FROM disttable; - f1 | not 2 -----+------- - 1 | t - 2 | f - 3 | t - | t -(4 rows) - -SELECT f1, f1 IS DISTINCT FROM NULL as "not null" FROM disttable; - f1 | not null -----+---------- - 1 | t - 2 | t - 3 | t - | f -(4 rows) - -SELECT f1, f1 IS DISTINCT FROM f1 as "false" FROM disttable; - f1 | false -----+------- - 1 | f - 2 | f - 3 | f - | f -(4 rows) - -SELECT f1, f1 IS DISTINCT FROM f1+1 as "not null" FROM disttable; - f1 | not null -----+---------- - 1 | t - 2 | t - 3 | t - | f -(4 rows) - --- check that optimizer constant-folds it properly -SELECT 1 IS DISTINCT FROM 2 as "yes"; - yes ------ - t -(1 row) - -SELECT 2 IS DISTINCT FROM 2 as "no"; - no ----- - f -(1 row) - -SELECT 2 IS DISTINCT FROM null as "yes"; - yes ------ - t -(1 row) - -SELECT null IS DISTINCT FROM null as "no"; - no ----- - f -(1 row) - --- negated form -SELECT 1 IS NOT DISTINCT FROM 2 as "no"; - no ----- - f -(1 row) - -SELECT 2 IS NOT DISTINCT FROM 2 as "yes"; - yes ------ - t -(1 row) - -SELECT 2 IS NOT DISTINCT FROM null as "no"; - no ----- - f -(1 row) - -SELECT null IS NOT DISTINCT FROM null as "yes"; - yes ------ - t -(1 row) - +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/select_having.out C:/cirrus/build/testrun/regress/regress/results/select_having.out --- C:/cirrus/src/test/regress/expected/select_having.out 2024-03-20 22:41:29.002394300 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/select_having.out 2024-03-20 22:44:01.621151700 +0000 @@ -1,93 +1,2 @@ --- --- SELECT_HAVING --- --- load test data -CREATE TABLE test_having (a int, b int, c char(8), d char); -INSERT INTO test_having VALUES (0, 1, 'XXXX', 'A'); -INSERT INTO test_having VALUES (1, 2, 'AAAA', 'b'); -INSERT INTO test_having VALUES (2, 2, 'AAAA', 'c'); -INSERT INTO test_having VALUES (3, 3, 'BBBB', 'D'); -INSERT INTO test_having VALUES (4, 3, 'BBBB', 'e'); -INSERT INTO test_having VALUES (5, 3, 'bbbb', 'F'); -INSERT INTO test_having VALUES (6, 4, 'cccc', 'g'); -INSERT INTO test_having VALUES (7, 4, 'cccc', 'h'); -INSERT INTO test_having VALUES (8, 4, 'CCCC', 'I'); -INSERT INTO test_having VALUES (9, 4, 'CCCC', 'j'); -SELECT b, c FROM test_having - GROUP BY b, c HAVING count(*) = 1 ORDER BY b, c; - b | c ----+---------- - 1 | XXXX - 3 | bbbb -(2 rows) - --- HAVING is effectively equivalent to WHERE in this case -SELECT b, c FROM test_having - GROUP BY b, c HAVING b = 3 ORDER BY b, c; - b | c ----+---------- - 3 | BBBB - 3 | bbbb -(2 rows) - -SELECT lower(c), count(c) FROM test_having - GROUP BY lower(c) HAVING count(*) > 2 OR min(a) = max(a) - ORDER BY lower(c); - lower | count --------+------- - bbbb | 3 - cccc | 4 - xxxx | 1 -(3 rows) - -SELECT c, max(a) FROM test_having - GROUP BY c HAVING count(*) > 2 OR min(a) = max(a) - ORDER BY c; - c | max -----------+----- - XXXX | 0 - bbbb | 5 -(2 rows) - --- test degenerate cases involving HAVING without GROUP BY --- Per SQL spec, these should generate 0 or 1 row, even without aggregates -SELECT min(a), max(a) FROM test_having HAVING min(a) = max(a); - min | max ------+----- -(0 rows) - -SELECT min(a), max(a) FROM test_having HAVING min(a) < max(a); - min | max ------+----- - 0 | 9 -(1 row) - --- errors: ungrouped column references -SELECT a FROM test_having HAVING min(a) < max(a); -ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: SELECT a FROM test_having HAVING min(a) < max(a); - ^ -SELECT 1 AS one FROM test_having HAVING a > 1; -ERROR: column "test_having.a" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: SELECT 1 AS one FROM test_having HAVING a > 1; - ^ --- the really degenerate case: need not scan table at all -SELECT 1 AS one FROM test_having HAVING 1 > 2; - one ------ -(0 rows) - -SELECT 1 AS one FROM test_having HAVING 1 < 2; - one ------ - 1 -(1 row) - --- and just to prove that we aren't scanning the table: -SELECT 1 AS one FROM test_having WHERE 1/a = 1 HAVING 1 < 2; - one ------ - 1 -(1 row) - -DROP TABLE test_having; +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/case.out C:/cirrus/build/testrun/regress/regress/results/case.out --- C:/cirrus/src/test/regress/expected/case.out 2024-03-20 22:41:28.852179500 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/case.out 2024-03-20 22:44:01.621151700 +0000 @@ -1,419 +1,2 @@ --- --- CASE --- Test the case statement --- -CREATE TABLE CASE_TBL ( - i integer, - f double precision -); -CREATE TABLE CASE2_TBL ( - i integer, - j integer -); -INSERT INTO CASE_TBL VALUES (1, 10.1); -INSERT INTO CASE_TBL VALUES (2, 20.2); -INSERT INTO CASE_TBL VALUES (3, -30.3); -INSERT INTO CASE_TBL VALUES (4, NULL); -INSERT INTO CASE2_TBL VALUES (1, -1); -INSERT INTO CASE2_TBL VALUES (2, -2); -INSERT INTO CASE2_TBL VALUES (3, -3); -INSERT INTO CASE2_TBL VALUES (2, -4); -INSERT INTO CASE2_TBL VALUES (1, NULL); -INSERT INTO CASE2_TBL VALUES (NULL, -6); --- --- Simplest examples without tables --- -SELECT '3' AS "One", - CASE - WHEN 1 < 2 THEN 3 - END AS "Simple WHEN"; - One | Simple WHEN ------+------------- - 3 | 3 -(1 row) - -SELECT '' AS "One", - CASE - WHEN 1 > 2 THEN 3 - END AS "Simple default"; - One | Simple default ---------+---------------- - | -(1 row) - -SELECT '3' AS "One", - CASE - WHEN 1 < 2 THEN 3 - ELSE 4 - END AS "Simple ELSE"; - One | Simple ELSE ------+------------- - 3 | 3 -(1 row) - -SELECT '4' AS "One", - CASE - WHEN 1 > 2 THEN 3 - ELSE 4 - END AS "ELSE default"; - One | ELSE default ------+-------------- - 4 | 4 -(1 row) - -SELECT '6' AS "One", - CASE - WHEN 1 > 2 THEN 3 - WHEN 4 < 5 THEN 6 - ELSE 7 - END AS "Two WHEN with default"; - One | Two WHEN with default ------+----------------------- - 6 | 6 -(1 row) - -SELECT '7' AS "None", - CASE WHEN random() < 0 THEN 1 - END AS "NULL on no matches"; - None | NULL on no matches -------+-------------------- - 7 | -(1 row) - --- Constant-expression folding shouldn't evaluate unreachable subexpressions -SELECT CASE WHEN 1=0 THEN 1/0 WHEN 1=1 THEN 1 ELSE 2/0 END; - case ------- - 1 -(1 row) - -SELECT CASE 1 WHEN 0 THEN 1/0 WHEN 1 THEN 1 ELSE 2/0 END; - case ------- - 1 -(1 row) - --- However we do not currently suppress folding of potentially --- reachable subexpressions -SELECT CASE WHEN i > 100 THEN 1/0 ELSE 0 END FROM case_tbl; -ERROR: division by zero --- Test for cases involving untyped literals in test expression -SELECT CASE 'a' WHEN 'a' THEN 1 ELSE 2 END; - case ------- - 1 -(1 row) - --- --- Examples of targets involving tables --- -SELECT - CASE - WHEN i >= 3 THEN i - END AS ">= 3 or Null" - FROM CASE_TBL; - >= 3 or Null --------------- - - - 3 - 4 -(4 rows) - -SELECT - CASE WHEN i >= 3 THEN (i + i) - ELSE i - END AS "Simplest Math" - FROM CASE_TBL; - Simplest Math ---------------- - 1 - 2 - 6 - 8 -(4 rows) - -SELECT i AS "Value", - CASE WHEN (i < 0) THEN 'small' - WHEN (i = 0) THEN 'zero' - WHEN (i = 1) THEN 'one' - WHEN (i = 2) THEN 'two' - ELSE 'big' - END AS "Category" - FROM CASE_TBL; - Value | Category --------+---------- - 1 | one - 2 | two - 3 | big - 4 | big -(4 rows) - -SELECT - CASE WHEN ((i < 0) or (i < 0)) THEN 'small' - WHEN ((i = 0) or (i = 0)) THEN 'zero' - WHEN ((i = 1) or (i = 1)) THEN 'one' - WHEN ((i = 2) or (i = 2)) THEN 'two' - ELSE 'big' - END AS "Category" - FROM CASE_TBL; - Category ----------- - one - two - big - big -(4 rows) - --- --- Examples of qualifications involving tables --- --- --- NULLIF() and COALESCE() --- Shorthand forms for typical CASE constructs --- defined in the SQL standard. --- -SELECT * FROM CASE_TBL WHERE COALESCE(f,i) = 4; - i | f ----+--- - 4 | -(1 row) - -SELECT * FROM CASE_TBL WHERE NULLIF(f,i) = 2; - i | f ----+--- -(0 rows) - -SELECT COALESCE(a.f, b.i, b.j) - FROM CASE_TBL a, CASE2_TBL b; - coalesce ----------- - 10.1 - 20.2 - -30.3 - 1 - 10.1 - 20.2 - -30.3 - 2 - 10.1 - 20.2 - -30.3 - 3 - 10.1 - 20.2 - -30.3 - 2 - 10.1 - 20.2 - -30.3 - 1 - 10.1 - 20.2 - -30.3 - -6 -(24 rows) - -SELECT * - FROM CASE_TBL a, CASE2_TBL b - WHERE COALESCE(a.f, b.i, b.j) = 2; - i | f | i | j ----+---+---+---- - 4 | | 2 | -2 - 4 | | 2 | -4 -(2 rows) - -SELECT NULLIF(a.i,b.i) AS "NULLIF(a.i,b.i)", - NULLIF(b.i, 4) AS "NULLIF(b.i,4)" - FROM CASE_TBL a, CASE2_TBL b; - NULLIF(a.i,b.i) | NULLIF(b.i,4) ------------------+--------------- - | 1 - 2 | 1 - 3 | 1 - 4 | 1 - 1 | 2 - | 2 - 3 | 2 - 4 | 2 - 1 | 3 - 2 | 3 - | 3 - 4 | 3 - 1 | 2 - | 2 - 3 | 2 - 4 | 2 - | 1 - 2 | 1 - 3 | 1 - 4 | 1 - 1 | - 2 | - 3 | - 4 | -(24 rows) - -SELECT * - FROM CASE_TBL a, CASE2_TBL b - WHERE COALESCE(f,b.i) = 2; - i | f | i | j ----+---+---+---- - 4 | | 2 | -2 - 4 | | 2 | -4 -(2 rows) - --- Tests for constant subexpression simplification -explain (costs off) -SELECT * FROM CASE_TBL WHERE NULLIF(1, 2) = 2; - QUERY PLAN --------------------------- - Result - One-Time Filter: false -(2 rows) - -explain (costs off) -SELECT * FROM CASE_TBL WHERE NULLIF(1, 1) IS NOT NULL; - QUERY PLAN --------------------------- - Result - One-Time Filter: false -(2 rows) - -explain (costs off) -SELECT * FROM CASE_TBL WHERE NULLIF(1, null) = 2; - QUERY PLAN --------------------------- - Result - One-Time Filter: false -(2 rows) - --- --- Examples of updates involving tables --- -UPDATE CASE_TBL - SET i = CASE WHEN i >= 3 THEN (- i) - ELSE (2 * i) END; -SELECT * FROM CASE_TBL; - i | f -----+------- - 2 | 10.1 - 4 | 20.2 - -3 | -30.3 - -4 | -(4 rows) - -UPDATE CASE_TBL - SET i = CASE WHEN i >= 2 THEN (2 * i) - ELSE (3 * i) END; -SELECT * FROM CASE_TBL; - i | f ------+------- - 4 | 10.1 - 8 | 20.2 - -9 | -30.3 - -12 | -(4 rows) - -UPDATE CASE_TBL - SET i = CASE WHEN b.i >= 2 THEN (2 * j) - ELSE (3 * j) END - FROM CASE2_TBL b - WHERE j = -CASE_TBL.i; -SELECT * FROM CASE_TBL; - i | f ------+------- - 8 | 20.2 - -9 | -30.3 - -12 | - -8 | 10.1 -(4 rows) - --- --- Nested CASE expressions --- --- This test exercises a bug caused by aliasing econtext->caseValue_isNull --- with the isNull argument of the inner CASE's CaseExpr evaluation. After --- evaluating the vol(null) expression in the inner CASE's second WHEN-clause, --- the isNull flag for the case test value incorrectly became true, causing --- the third WHEN-clause not to match. The volatile function calls are needed --- to prevent constant-folding in the planner, which would hide the bug. --- Wrap this in a single transaction so the transient '=' operator doesn't --- cause problems in concurrent sessions -BEGIN; -CREATE FUNCTION vol(text) returns text as - 'begin return $1; end' language plpgsql volatile; -SELECT CASE - (CASE vol('bar') - WHEN 'foo' THEN 'it was foo!' - WHEN vol(null) THEN 'null input' - WHEN 'bar' THEN 'it was bar!' END - ) - WHEN 'it was foo!' THEN 'foo recognized' - WHEN 'it was bar!' THEN 'bar recognized' - ELSE 'unrecognized' END; - case ----------------- - bar recognized -(1 row) - --- In this case, we can't inline the SQL function without confusing things. -CREATE DOMAIN foodomain AS text; -CREATE FUNCTION volfoo(text) returns foodomain as - 'begin return $1::foodomain; end' language plpgsql volatile; -CREATE FUNCTION inline_eq(foodomain, foodomain) returns boolean as - 'SELECT CASE $2::text WHEN $1::text THEN true ELSE false END' language sql; -CREATE OPERATOR = (procedure = inline_eq, - leftarg = foodomain, rightarg = foodomain); -SELECT CASE volfoo('bar') WHEN 'foo'::foodomain THEN 'is foo' ELSE 'is not foo' END; - case ------------- - is not foo -(1 row) - -ROLLBACK; --- Test multiple evaluation of a CASE arg that is a read/write object (#14472) --- Wrap this in a single transaction so the transient '=' operator doesn't --- cause problems in concurrent sessions -BEGIN; -CREATE DOMAIN arrdomain AS int[]; -CREATE FUNCTION make_ad(int,int) returns arrdomain as - 'declare x arrdomain; - begin - x := array[$1,$2]; - return x; - end' language plpgsql volatile; -CREATE FUNCTION ad_eq(arrdomain, arrdomain) returns boolean as - 'begin return array_eq($1, $2); end' language plpgsql; -CREATE OPERATOR = (procedure = ad_eq, - leftarg = arrdomain, rightarg = arrdomain); -SELECT CASE make_ad(1,2) - WHEN array[2,4]::arrdomain THEN 'wrong' - WHEN array[2,5]::arrdomain THEN 'still wrong' - WHEN array[1,2]::arrdomain THEN 'right' - END; - case -------- - right -(1 row) - -ROLLBACK; --- Test interaction of CASE with ArrayCoerceExpr (bug #15471) -BEGIN; -CREATE TYPE casetestenum AS ENUM ('e', 'f', 'g'); -SELECT - CASE 'foo'::text - WHEN 'foo' THEN ARRAY['a', 'b', 'c', 'd'] || enum_range(NULL::casetestenum)::text[] - ELSE ARRAY['x', 'y'] - END; - array ------------------ - {a,b,c,d,e,f,g} -(1 row) - -ROLLBACK; --- --- Clean up --- -DROP TABLE CASE_TBL; -DROP TABLE CASE2_TBL; +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/aggregates.out C:/cirrus/build/testrun/regress/regress/results/aggregates.out --- C:/cirrus/src/test/regress/expected/aggregates.out 2024-03-20 22:41:28.830503700 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/aggregates.out 2024-03-20 22:44:01.621151700 +0000 @@ -1,3328 +1,2 @@ --- --- AGGREGATES --- --- directory paths are passed to us in environment variables -\getenv abs_srcdir PG_ABS_SRCDIR --- avoid bit-exact output here because operations may not be bit-exact. -SET extra_float_digits = 0; --- prepare some test data -CREATE TABLE aggtest ( - a int2, - b float4 -); -\set filename :abs_srcdir '/data/agg.data' -COPY aggtest FROM :'filename'; -ANALYZE aggtest; -SELECT avg(four) AS avg_1 FROM onek; - avg_1 --------------------- - 1.5000000000000000 -(1 row) - -SELECT avg(a) AS avg_32 FROM aggtest WHERE a < 100; - avg_32 ---------------------- - 32.6666666666666667 -(1 row) - -SELECT any_value(v) FROM (VALUES (1), (2), (3)) AS v (v); - any_value ------------ - 1 -(1 row) - -SELECT any_value(v) FROM (VALUES (NULL)) AS v (v); - any_value ------------ - -(1 row) - -SELECT any_value(v) FROM (VALUES (NULL), (1), (2)) AS v (v); - any_value ------------ - 1 -(1 row) - -SELECT any_value(v) FROM (VALUES (array['hello', 'world'])) AS v (v); - any_value ---------------- - {hello,world} -(1 row) - --- In 7.1, avg(float4) is computed using float8 arithmetic. --- Round the result to 3 digits to avoid platform-specific results. -SELECT avg(b)::numeric(10,3) AS avg_107_943 FROM aggtest; - avg_107_943 -------------- - 107.943 -(1 row) - -SELECT avg(gpa) AS avg_3_4 FROM ONLY student; - avg_3_4 ---------- - 3.4 -(1 row) - -SELECT sum(four) AS sum_1500 FROM onek; - sum_1500 ----------- - 1500 -(1 row) - -SELECT sum(a) AS sum_198 FROM aggtest; - sum_198 ---------- - 198 -(1 row) - -SELECT sum(b) AS avg_431_773 FROM aggtest; - avg_431_773 -------------- - 431.773 -(1 row) - -SELECT sum(gpa) AS avg_6_8 FROM ONLY student; - avg_6_8 ---------- - 6.8 -(1 row) - -SELECT max(four) AS max_3 FROM onek; - max_3 -------- - 3 -(1 row) - -SELECT max(a) AS max_100 FROM aggtest; - max_100 ---------- - 100 -(1 row) - -SELECT max(aggtest.b) AS max_324_78 FROM aggtest; - max_324_78 ------------- - 324.78 -(1 row) - -SELECT max(student.gpa) AS max_3_7 FROM student; - max_3_7 ---------- - 3.7 -(1 row) - -SELECT stddev_pop(b) FROM aggtest; - stddev_pop ------------------ - 131.10703231895 -(1 row) - -SELECT stddev_samp(b) FROM aggtest; - stddev_samp ------------------- - 151.389360803998 -(1 row) - -SELECT var_pop(b) FROM aggtest; - var_pop ------------------- - 17189.0539234823 -(1 row) - -SELECT var_samp(b) FROM aggtest; - var_samp ------------------- - 22918.7385646431 -(1 row) - -SELECT stddev_pop(b::numeric) FROM aggtest; - stddev_pop ------------------- - 131.107032862199 -(1 row) - -SELECT stddev_samp(b::numeric) FROM aggtest; - stddev_samp ------------------- - 151.389361431288 -(1 row) - -SELECT var_pop(b::numeric) FROM aggtest; - var_pop --------------------- - 17189.054065929769 -(1 row) - -SELECT var_samp(b::numeric) FROM aggtest; - var_samp --------------------- - 22918.738754573025 -(1 row) - --- population variance is defined for a single tuple, sample variance --- is not -SELECT var_pop(1.0::float8), var_samp(2.0::float8); - var_pop | var_samp ----------+---------- - 0 | -(1 row) - -SELECT stddev_pop(3.0::float8), stddev_samp(4.0::float8); - stddev_pop | stddev_samp -------------+------------- - 0 | -(1 row) - -SELECT var_pop('inf'::float8), var_samp('inf'::float8); - var_pop | var_samp ----------+---------- - NaN | -(1 row) - -SELECT stddev_pop('inf'::float8), stddev_samp('inf'::float8); - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - -SELECT var_pop('nan'::float8), var_samp('nan'::float8); - var_pop | var_samp ----------+---------- - NaN | -(1 row) - -SELECT stddev_pop('nan'::float8), stddev_samp('nan'::float8); - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - -SELECT var_pop(1.0::float4), var_samp(2.0::float4); - var_pop | var_samp ----------+---------- - 0 | -(1 row) - -SELECT stddev_pop(3.0::float4), stddev_samp(4.0::float4); - stddev_pop | stddev_samp -------------+------------- - 0 | -(1 row) - -SELECT var_pop('inf'::float4), var_samp('inf'::float4); - var_pop | var_samp ----------+---------- - NaN | -(1 row) - -SELECT stddev_pop('inf'::float4), stddev_samp('inf'::float4); - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - -SELECT var_pop('nan'::float4), var_samp('nan'::float4); - var_pop | var_samp ----------+---------- - NaN | -(1 row) - -SELECT stddev_pop('nan'::float4), stddev_samp('nan'::float4); - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - -SELECT var_pop(1.0::numeric), var_samp(2.0::numeric); - var_pop | var_samp ----------+---------- - 0 | -(1 row) - -SELECT stddev_pop(3.0::numeric), stddev_samp(4.0::numeric); - stddev_pop | stddev_samp -------------+------------- - 0 | -(1 row) - -SELECT var_pop('inf'::numeric), var_samp('inf'::numeric); - var_pop | var_samp ----------+---------- - NaN | -(1 row) - -SELECT stddev_pop('inf'::numeric), stddev_samp('inf'::numeric); - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - -SELECT var_pop('nan'::numeric), var_samp('nan'::numeric); - var_pop | var_samp ----------+---------- - NaN | -(1 row) - -SELECT stddev_pop('nan'::numeric), stddev_samp('nan'::numeric); - stddev_pop | stddev_samp -------------+------------- - NaN | -(1 row) - --- verify correct results for null and NaN inputs -select sum(null::int4) from generate_series(1,3); - sum ------ - -(1 row) - -select sum(null::int8) from generate_series(1,3); - sum ------ - -(1 row) - -select sum(null::numeric) from generate_series(1,3); - sum ------ - -(1 row) - -select sum(null::float8) from generate_series(1,3); - sum ------ - -(1 row) - -select avg(null::int4) from generate_series(1,3); - avg ------ - -(1 row) - -select avg(null::int8) from generate_series(1,3); - avg ------ - -(1 row) - -select avg(null::numeric) from generate_series(1,3); - avg ------ - -(1 row) - -select avg(null::float8) from generate_series(1,3); - avg ------ - -(1 row) - -select sum('NaN'::numeric) from generate_series(1,3); - sum ------ - NaN -(1 row) - -select avg('NaN'::numeric) from generate_series(1,3); - avg ------ - NaN -(1 row) - --- verify correct results for infinite inputs -SELECT sum(x::float8), avg(x::float8), var_pop(x::float8) -FROM (VALUES ('1'), ('infinity')) v(x); - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - -SELECT sum(x::float8), avg(x::float8), var_pop(x::float8) -FROM (VALUES ('infinity'), ('1')) v(x); - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - -SELECT sum(x::float8), avg(x::float8), var_pop(x::float8) -FROM (VALUES ('infinity'), ('infinity')) v(x); - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - -SELECT sum(x::float8), avg(x::float8), var_pop(x::float8) -FROM (VALUES ('-infinity'), ('infinity')) v(x); - sum | avg | var_pop ------+-----+--------- - NaN | NaN | NaN -(1 row) - -SELECT sum(x::float8), avg(x::float8), var_pop(x::float8) -FROM (VALUES ('-infinity'), ('-infinity')) v(x); - sum | avg | var_pop ------------+-----------+--------- - -Infinity | -Infinity | NaN -(1 row) - -SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric) -FROM (VALUES ('1'), ('infinity')) v(x); - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - -SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric) -FROM (VALUES ('infinity'), ('1')) v(x); - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - -SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric) -FROM (VALUES ('infinity'), ('infinity')) v(x); - sum | avg | var_pop -----------+----------+--------- - Infinity | Infinity | NaN -(1 row) - -SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric) -FROM (VALUES ('-infinity'), ('infinity')) v(x); - sum | avg | var_pop ------+-----+--------- - NaN | NaN | NaN -(1 row) - -SELECT sum(x::numeric), avg(x::numeric), var_pop(x::numeric) -FROM (VALUES ('-infinity'), ('-infinity')) v(x); - sum | avg | var_pop ------------+-----------+--------- - -Infinity | -Infinity | NaN -(1 row) - --- test accuracy with a large input offset -SELECT avg(x::float8), var_pop(x::float8) -FROM (VALUES (100000003), (100000004), (100000006), (100000007)) v(x); - avg | var_pop ------------+--------- - 100000005 | 2.5 -(1 row) - -SELECT avg(x::float8), var_pop(x::float8) -FROM (VALUES (7000000000005), (7000000000007)) v(x); - avg | var_pop ----------------+--------- - 7000000000006 | 1 -(1 row) - --- SQL2003 binary aggregates -SELECT regr_count(b, a) FROM aggtest; - regr_count ------------- - 4 -(1 row) - -SELECT regr_sxx(b, a) FROM aggtest; - regr_sxx ----------- - 5099 -(1 row) - -SELECT regr_syy(b, a) FROM aggtest; - regr_syy ------------------- - 68756.2156939293 -(1 row) - -SELECT regr_sxy(b, a) FROM aggtest; - regr_sxy ------------------- - 2614.51582155004 -(1 row) - -SELECT regr_avgx(b, a), regr_avgy(b, a) FROM aggtest; - regr_avgx | regr_avgy ------------+------------------ - 49.5 | 107.943152273074 -(1 row) - -SELECT regr_r2(b, a) FROM aggtest; - regr_r2 --------------------- - 0.0194977982031803 -(1 row) - -SELECT regr_slope(b, a), regr_intercept(b, a) FROM aggtest; - regr_slope | regr_intercept --------------------+------------------ - 0.512750700441271 | 82.5619926012309 -(1 row) - -SELECT covar_pop(b, a), covar_samp(b, a) FROM aggtest; - covar_pop | covar_samp ------------------+------------------ - 653.62895538751 | 871.505273850014 -(1 row) - -SELECT corr(b, a) FROM aggtest; - corr -------------------- - 0.139634516517873 -(1 row) - --- check single-tuple behavior -SELECT covar_pop(1::float8,2::float8), covar_samp(3::float8,4::float8); - covar_pop | covar_samp ------------+------------ - 0 | -(1 row) - -SELECT covar_pop(1::float8,'inf'::float8), covar_samp(3::float8,'inf'::float8); - covar_pop | covar_samp ------------+------------ - NaN | -(1 row) - -SELECT covar_pop(1::float8,'nan'::float8), covar_samp(3::float8,'nan'::float8); - covar_pop | covar_samp ------------+------------ - NaN | -(1 row) - --- test accum and combine functions directly -CREATE TABLE regr_test (x float8, y float8); -INSERT INTO regr_test VALUES (10,150),(20,250),(30,350),(80,540),(100,200); -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (10,20,30,80); - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+------+----------+---------- - 4 | 140 | 2900 | 1290 | 83075 | 15050 -(1 row) - -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test; - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+------+----------+---------- - 5 | 240 | 6280 | 1490 | 95080 | 8680 -(1 row) - -SELECT float8_accum('{4,140,2900}'::float8[], 100); - float8_accum --------------- - {5,240,6280} -(1 row) - -SELECT float8_regr_accum('{4,140,2900,1290,83075,15050}'::float8[], 200, 100); - float8_regr_accum ------------------------------- - {5,240,6280,1490,95080,8680} -(1 row) - -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (10,20,30); - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+-----+----------+---------- - 3 | 60 | 200 | 750 | 20000 | 2000 -(1 row) - -SELECT count(*), sum(x), regr_sxx(y,x), sum(y),regr_syy(y,x), regr_sxy(y,x) -FROM regr_test WHERE x IN (80,100); - count | sum | regr_sxx | sum | regr_syy | regr_sxy --------+-----+----------+-----+----------+---------- - 2 | 180 | 200 | 740 | 57800 | -3400 -(1 row) - -SELECT float8_combine('{3,60,200}'::float8[], '{0,0,0}'::float8[]); - float8_combine ----------------- - {3,60,200} -(1 row) - -SELECT float8_combine('{0,0,0}'::float8[], '{2,180,200}'::float8[]); - float8_combine ----------------- - {2,180,200} -(1 row) - -SELECT float8_combine('{3,60,200}'::float8[], '{2,180,200}'::float8[]); - float8_combine ----------------- - {5,240,6280} -(1 row) - -SELECT float8_regr_combine('{3,60,200,750,20000,2000}'::float8[], - '{0,0,0,0,0,0}'::float8[]); - float8_regr_combine ---------------------------- - {3,60,200,750,20000,2000} -(1 row) - -SELECT float8_regr_combine('{0,0,0,0,0,0}'::float8[], - '{2,180,200,740,57800,-3400}'::float8[]); - float8_regr_combine ------------------------------ - {2,180,200,740,57800,-3400} -(1 row) - -SELECT float8_regr_combine('{3,60,200,750,20000,2000}'::float8[], - '{2,180,200,740,57800,-3400}'::float8[]); - float8_regr_combine ------------------------------- - {5,240,6280,1490,95080,8680} -(1 row) - -DROP TABLE regr_test; --- test count, distinct -SELECT count(four) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - -SELECT count(DISTINCT four) AS cnt_4 FROM onek; - cnt_4 -------- - 4 -(1 row) - -select ten, count(*), sum(four) from onek -group by ten order by ten; - ten | count | sum ------+-------+----- - 0 | 100 | 100 - 1 | 100 | 200 - 2 | 100 | 100 - 3 | 100 | 200 - 4 | 100 | 100 - 5 | 100 | 200 - 6 | 100 | 100 - 7 | 100 | 200 - 8 | 100 | 100 - 9 | 100 | 200 -(10 rows) - -select ten, count(four), sum(DISTINCT four) from onek -group by ten order by ten; - ten | count | sum ------+-------+----- - 0 | 100 | 2 - 1 | 100 | 4 - 2 | 100 | 2 - 3 | 100 | 4 - 4 | 100 | 2 - 5 | 100 | 4 - 6 | 100 | 2 - 7 | 100 | 4 - 8 | 100 | 2 - 9 | 100 | 4 -(10 rows) - --- user-defined aggregates -SELECT newavg(four) AS avg_1 FROM onek; - avg_1 --------------------- - 1.5000000000000000 -(1 row) - -SELECT newsum(four) AS sum_1500 FROM onek; - sum_1500 ----------- - 1500 -(1 row) - -SELECT newcnt(four) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - -SELECT newcnt(*) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - -SELECT oldcnt(*) AS cnt_1000 FROM onek; - cnt_1000 ----------- - 1000 -(1 row) - -SELECT sum2(q1,q2) FROM int8_tbl; - sum2 -------------------- - 18271560493827981 -(1 row) - --- test for outer-level aggregates --- this should work -select ten, sum(distinct four) from onek a -group by ten -having exists (select 1 from onek b where sum(distinct a.four) = b.four); - ten | sum ------+----- - 0 | 2 - 2 | 2 - 4 | 2 - 6 | 2 - 8 | 2 -(5 rows) - --- this should fail because subquery has an agg of its own in WHERE -select ten, sum(distinct four) from onek a -group by ten -having exists (select 1 from onek b - where sum(distinct a.four + b.four) = b.four); -ERROR: aggregate functions are not allowed in WHERE -LINE 4: where sum(distinct a.four + b.four) = b.four)... - ^ --- Test handling of sublinks within outer-level aggregates. --- Per bug report from Daniel Grace. -select - (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1))) -from tenk1 o; - max ------- - 9999 -(1 row) - --- Test handling of Params within aggregate arguments in hashed aggregation. --- Per bug report from Jeevan Chalke. -explain (verbose, costs off) -select s1, s2, sm -from generate_series(1, 3) s1, - lateral (select s2, sum(s1 + s2) sm - from generate_series(1, 3) s2 group by s2) ss -order by 1, 2; - QUERY PLAN ------------------------------------------------------------------- - Sort - Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2))) - Sort Key: s1.s1, s2.s2 - -> Nested Loop - Output: s1.s1, s2.s2, (sum((s1.s1 + s2.s2))) - -> Function Scan on pg_catalog.generate_series s1 - Output: s1.s1 - Function Call: generate_series(1, 3) - -> HashAggregate - Output: s2.s2, sum((s1.s1 + s2.s2)) - Group Key: s2.s2 - -> Function Scan on pg_catalog.generate_series s2 - Output: s2.s2 - Function Call: generate_series(1, 3) -(14 rows) - -select s1, s2, sm -from generate_series(1, 3) s1, - lateral (select s2, sum(s1 + s2) sm - from generate_series(1, 3) s2 group by s2) ss -order by 1, 2; - s1 | s2 | sm -----+----+---- - 1 | 1 | 2 - 1 | 2 | 3 - 1 | 3 | 4 - 2 | 1 | 3 - 2 | 2 | 4 - 2 | 3 | 5 - 3 | 1 | 4 - 3 | 2 | 5 - 3 | 3 | 6 -(9 rows) - -explain (verbose, costs off) -select array(select sum(x+y) s - from generate_series(1,3) y group by y order by s) - from generate_series(1,3) x; - QUERY PLAN -------------------------------------------------------------------- - Function Scan on pg_catalog.generate_series x - Output: ARRAY(SubPlan 1) - Function Call: generate_series(1, 3) - SubPlan 1 - -> Sort - Output: (sum((x.x + y.y))), y.y - Sort Key: (sum((x.x + y.y))) - -> HashAggregate - Output: sum((x.x + y.y)), y.y - Group Key: y.y - -> Function Scan on pg_catalog.generate_series y - Output: y.y - Function Call: generate_series(1, 3) -(13 rows) - -select array(select sum(x+y) s - from generate_series(1,3) y group by y order by s) - from generate_series(1,3) x; - array ---------- - {2,3,4} - {3,4,5} - {4,5,6} -(3 rows) - --- --- test for bitwise integer aggregates --- -CREATE TEMPORARY TABLE bitwise_test( - i2 INT2, - i4 INT4, - i8 INT8, - i INTEGER, - x INT2, - y BIT(4) -); --- empty case -SELECT - BIT_AND(i2) AS "?", - BIT_OR(i4) AS "?", - BIT_XOR(i8) AS "?" -FROM bitwise_test; - ? | ? | ? ----+---+--- - | | -(1 row) - -COPY bitwise_test FROM STDIN NULL 'null'; -SELECT - BIT_AND(i2) AS "1", - BIT_AND(i4) AS "1", - BIT_AND(i8) AS "1", - BIT_AND(i) AS "?", - BIT_AND(x) AS "0", - BIT_AND(y) AS "0100", - BIT_OR(i2) AS "7", - BIT_OR(i4) AS "7", - BIT_OR(i8) AS "7", - BIT_OR(i) AS "?", - BIT_OR(x) AS "7", - BIT_OR(y) AS "1101", - BIT_XOR(i2) AS "5", - BIT_XOR(i4) AS "5", - BIT_XOR(i8) AS "5", - BIT_XOR(i) AS "?", - BIT_XOR(x) AS "7", - BIT_XOR(y) AS "1101" -FROM bitwise_test; - 1 | 1 | 1 | ? | 0 | 0100 | 7 | 7 | 7 | ? | 7 | 1101 | 5 | 5 | 5 | ? | 7 | 1101 ----+---+---+---+---+------+---+---+---+---+---+------+---+---+---+---+---+------ - 1 | 1 | 1 | 1 | 0 | 0100 | 7 | 7 | 7 | 3 | 7 | 1101 | 5 | 5 | 5 | 2 | 7 | 1101 -(1 row) - --- --- test boolean aggregates --- --- first test all possible transition and final states -SELECT - -- boolean and transitions - -- null because strict - booland_statefunc(NULL, NULL) IS NULL AS "t", - booland_statefunc(TRUE, NULL) IS NULL AS "t", - booland_statefunc(FALSE, NULL) IS NULL AS "t", - booland_statefunc(NULL, TRUE) IS NULL AS "t", - booland_statefunc(NULL, FALSE) IS NULL AS "t", - -- and actual computations - booland_statefunc(TRUE, TRUE) AS "t", - NOT booland_statefunc(TRUE, FALSE) AS "t", - NOT booland_statefunc(FALSE, TRUE) AS "t", - NOT booland_statefunc(FALSE, FALSE) AS "t"; - t | t | t | t | t | t | t | t | t ----+---+---+---+---+---+---+---+--- - t | t | t | t | t | t | t | t | t -(1 row) - -SELECT - -- boolean or transitions - -- null because strict - boolor_statefunc(NULL, NULL) IS NULL AS "t", - boolor_statefunc(TRUE, NULL) IS NULL AS "t", - boolor_statefunc(FALSE, NULL) IS NULL AS "t", - boolor_statefunc(NULL, TRUE) IS NULL AS "t", - boolor_statefunc(NULL, FALSE) IS NULL AS "t", - -- actual computations - boolor_statefunc(TRUE, TRUE) AS "t", - boolor_statefunc(TRUE, FALSE) AS "t", - boolor_statefunc(FALSE, TRUE) AS "t", - NOT boolor_statefunc(FALSE, FALSE) AS "t"; - t | t | t | t | t | t | t | t | t ----+---+---+---+---+---+---+---+--- - t | t | t | t | t | t | t | t | t -(1 row) - -CREATE TEMPORARY TABLE bool_test( - b1 BOOL, - b2 BOOL, - b3 BOOL, - b4 BOOL); --- empty case -SELECT - BOOL_AND(b1) AS "n", - BOOL_OR(b3) AS "n" -FROM bool_test; - n | n ----+--- - | -(1 row) - -COPY bool_test FROM STDIN NULL 'null'; -SELECT - BOOL_AND(b1) AS "f", - BOOL_AND(b2) AS "t", - BOOL_AND(b3) AS "f", - BOOL_AND(b4) AS "n", - BOOL_AND(NOT b2) AS "f", - BOOL_AND(NOT b3) AS "t" -FROM bool_test; - f | t | f | n | f | t ----+---+---+---+---+--- - f | t | f | | f | t -(1 row) - -SELECT - EVERY(b1) AS "f", - EVERY(b2) AS "t", - EVERY(b3) AS "f", - EVERY(b4) AS "n", - EVERY(NOT b2) AS "f", - EVERY(NOT b3) AS "t" -FROM bool_test; - f | t | f | n | f | t ----+---+---+---+---+--- - f | t | f | | f | t -(1 row) - -SELECT - BOOL_OR(b1) AS "t", - BOOL_OR(b2) AS "t", - BOOL_OR(b3) AS "f", - BOOL_OR(b4) AS "n", - BOOL_OR(NOT b2) AS "f", - BOOL_OR(NOT b3) AS "t" -FROM bool_test; - t | t | f | n | f | t ----+---+---+---+---+--- - t | t | f | | f | t -(1 row) - --- --- Test cases that should be optimized into indexscans instead of --- the generic aggregate implementation. --- --- Basic cases -explain (costs off) - select min(unique1) from tenk1; - QUERY PLAN ------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan using tenk1_unique1 on tenk1 - Index Cond: (unique1 IS NOT NULL) -(5 rows) - -select min(unique1) from tenk1; - min ------ - 0 -(1 row) - -explain (costs off) - select max(unique1) from tenk1; - QUERY PLAN ---------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique1 on tenk1 - Index Cond: (unique1 IS NOT NULL) -(5 rows) - -select max(unique1) from tenk1; - max ------- - 9999 -(1 row) - -explain (costs off) - select max(unique1) from tenk1 where unique1 < 42; - QUERY PLAN ------------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique1 on tenk1 - Index Cond: ((unique1 IS NOT NULL) AND (unique1 < 42)) -(5 rows) - -select max(unique1) from tenk1 where unique1 < 42; - max ------ - 41 -(1 row) - -explain (costs off) - select max(unique1) from tenk1 where unique1 > 42; - QUERY PLAN ------------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique1 on tenk1 - Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42)) -(5 rows) - -select max(unique1) from tenk1 where unique1 > 42; - max ------- - 9999 -(1 row) - --- the planner may choose a generic aggregate here if parallel query is --- enabled, since that plan will be parallel safe and the "optimized" --- plan, which has almost identical cost, will not be. we want to test --- the optimized plan, so temporarily disable parallel query. -begin; -set local max_parallel_workers_per_gather = 0; -explain (costs off) - select max(unique1) from tenk1 where unique1 > 42000; - QUERY PLAN ---------------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique1 on tenk1 - Index Cond: ((unique1 IS NOT NULL) AND (unique1 > 42000)) -(5 rows) - -select max(unique1) from tenk1 where unique1 > 42000; - max ------ - -(1 row) - -rollback; --- multi-column index (uses tenk1_thous_tenthous) -explain (costs off) - select max(tenthous) from tenk1 where thousand = 33; - QUERY PLAN ----------------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_thous_tenthous on tenk1 - Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL)) -(5 rows) - -select max(tenthous) from tenk1 where thousand = 33; - max ------- - 9033 -(1 row) - -explain (costs off) - select min(tenthous) from tenk1 where thousand = 33; - QUERY PLAN --------------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Index Only Scan using tenk1_thous_tenthous on tenk1 - Index Cond: ((thousand = 33) AND (tenthous IS NOT NULL)) -(5 rows) - -select min(tenthous) from tenk1 where thousand = 33; - min ------ - 33 -(1 row) - --- check parameter propagation into an indexscan subquery -explain (costs off) - select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt - from int4_tbl; - QUERY PLAN ------------------------------------------------------------------------------------------ - Seq Scan on int4_tbl - SubPlan 2 - -> Result - InitPlan 1 - -> Limit - -> Index Only Scan using tenk1_unique1 on tenk1 - Index Cond: ((unique1 IS NOT NULL) AND (unique1 > int4_tbl.f1)) -(7 rows) - -select f1, (select min(unique1) from tenk1 where unique1 > f1) AS gt - from int4_tbl; - f1 | gt --------------+---- - 0 | 1 - 123456 | - -123456 | 0 - 2147483647 | - -2147483647 | 0 -(5 rows) - --- check some cases that were handled incorrectly in 8.3.0 -explain (costs off) - select distinct max(unique2) from tenk1; - QUERY PLAN ---------------------------------------------------------------------- - HashAggregate - Group Key: (InitPlan 1).col1 - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique2 on tenk1 - Index Cond: (unique2 IS NOT NULL) - -> Result -(7 rows) - -select distinct max(unique2) from tenk1; - max ------- - 9999 -(1 row) - -explain (costs off) - select max(unique2) from tenk1 order by 1; - QUERY PLAN ---------------------------------------------------------------------- - Sort - Sort Key: ((InitPlan 1).col1) - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique2 on tenk1 - Index Cond: (unique2 IS NOT NULL) - -> Result -(7 rows) - -select max(unique2) from tenk1 order by 1; - max ------- - 9999 -(1 row) - -explain (costs off) - select max(unique2) from tenk1 order by max(unique2); - QUERY PLAN ---------------------------------------------------------------------- - Sort - Sort Key: ((InitPlan 1).col1) - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique2 on tenk1 - Index Cond: (unique2 IS NOT NULL) - -> Result -(7 rows) - -select max(unique2) from tenk1 order by max(unique2); - max ------- - 9999 -(1 row) - -explain (costs off) - select max(unique2) from tenk1 order by max(unique2)+1; - QUERY PLAN ---------------------------------------------------------------------- - Sort - Sort Key: (((InitPlan 1).col1 + 1)) - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique2 on tenk1 - Index Cond: (unique2 IS NOT NULL) - -> Result -(7 rows) - -select max(unique2) from tenk1 order by max(unique2)+1; - max ------- - 9999 -(1 row) - -explain (costs off) - select max(unique2), generate_series(1,3) as g from tenk1 order by g desc; - QUERY PLAN ---------------------------------------------------------------------- - Sort - Sort Key: (generate_series(1, 3)) DESC - InitPlan 1 - -> Limit - -> Index Only Scan Backward using tenk1_unique2 on tenk1 - Index Cond: (unique2 IS NOT NULL) - -> ProjectSet - -> Result -(8 rows) - -select max(unique2), generate_series(1,3) as g from tenk1 order by g desc; - max | g -------+--- - 9999 | 3 - 9999 | 2 - 9999 | 1 -(3 rows) - --- interesting corner case: constant gets optimized into a seqscan -explain (costs off) - select max(100) from tenk1; - QUERY PLAN ----------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Result - One-Time Filter: (100 IS NOT NULL) - -> Seq Scan on tenk1 -(6 rows) - -select max(100) from tenk1; - max ------ - 100 -(1 row) - --- try it on an inheritance tree -create table minmaxtest(f1 int); -create table minmaxtest1() inherits (minmaxtest); -create table minmaxtest2() inherits (minmaxtest); -create table minmaxtest3() inherits (minmaxtest); -create index minmaxtesti on minmaxtest(f1); -create index minmaxtest1i on minmaxtest1(f1); -create index minmaxtest2i on minmaxtest2(f1 desc); -create index minmaxtest3i on minmaxtest3(f1) where f1 is not null; -insert into minmaxtest values(11), (12); -insert into minmaxtest1 values(13), (14); -insert into minmaxtest2 values(15), (16); -insert into minmaxtest3 values(17), (18); -explain (costs off) - select min(f1), max(f1) from minmaxtest; - QUERY PLAN ---------------------------------------------------------------------------------------------- - Result - InitPlan 1 - -> Limit - -> Merge Append - Sort Key: minmaxtest.f1 - -> Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4 - InitPlan 2 - -> Limit - -> Merge Append - Sort Key: minmaxtest_5.f1 DESC - -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9 -(23 rows) - -select min(f1), max(f1) from minmaxtest; - min | max ------+----- - 11 | 18 -(1 row) - --- DISTINCT doesn't do anything useful here, but it shouldn't fail -explain (costs off) - select distinct min(f1), max(f1) from minmaxtest; - QUERY PLAN ---------------------------------------------------------------------------------------------- - Unique - InitPlan 1 - -> Limit - -> Merge Append - Sort Key: minmaxtest.f1 - -> Index Only Scan using minmaxtesti on minmaxtest minmaxtest_1 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest1i on minmaxtest1 minmaxtest_2 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest2i on minmaxtest2 minmaxtest_3 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest3i on minmaxtest3 minmaxtest_4 - InitPlan 2 - -> Limit - -> Merge Append - Sort Key: minmaxtest_5.f1 DESC - -> Index Only Scan Backward using minmaxtesti on minmaxtest minmaxtest_6 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest1i on minmaxtest1 minmaxtest_7 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan using minmaxtest2i on minmaxtest2 minmaxtest_8 - Index Cond: (f1 IS NOT NULL) - -> Index Only Scan Backward using minmaxtest3i on minmaxtest3 minmaxtest_9 - -> Sort - Sort Key: ((InitPlan 1).col1), ((InitPlan 2).col1) - -> Result -(26 rows) - -select distinct min(f1), max(f1) from minmaxtest; - min | max ------+----- - 11 | 18 -(1 row) - -drop table minmaxtest cascade; -NOTICE: drop cascades to 3 other objects -DETAIL: drop cascades to table minmaxtest1 -drop cascades to table minmaxtest2 -drop cascades to table minmaxtest3 --- check for correct detection of nested-aggregate errors -select max(min(unique1)) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select max(min(unique1)) from tenk1; - ^ -select (select max(min(unique1)) from int8_tbl) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select (select max(min(unique1)) from int8_tbl) from tenk1; - ^ -select avg((select avg(a1.col1 order by (select avg(a2.col2) from tenk1 a3)) - from tenk1 a1(col1))) -from tenk1 a2(col2); -ERROR: aggregate function calls cannot be nested -LINE 1: select avg((select avg(a1.col1 order by (select avg(a2.col2)... - ^ --- --- Test removal of redundant GROUP BY columns --- -create temp table t1 (a int, b int, c int, d int, primary key (a, b)); -create temp table t2 (x int, y int, z int, primary key (x, y)); -create temp table t3 (a int, b int, c int, primary key(a, b) deferrable); --- Non-primary-key columns can be removed from GROUP BY -explain (costs off) select * from t1 group by a,b,c,d; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a, b - -> Seq Scan on t1 -(3 rows) - --- No removal can happen if the complete PK is not present in GROUP BY -explain (costs off) select a,c from t1 group by a,c,d; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a, c, d - -> Seq Scan on t1 -(3 rows) - --- Test removal across multiple relations -explain (costs off) select * -from t1 inner join t2 on t1.a = t2.x and t1.b = t2.y -group by t1.a,t1.b,t1.c,t1.d,t2.x,t2.y,t2.z; - QUERY PLAN ------------------------------------------------------- - HashAggregate - Group Key: t1.a, t1.b - -> Hash Join - Hash Cond: ((t2.x = t1.a) AND (t2.y = t1.b)) - -> Seq Scan on t2 - -> Hash - -> Seq Scan on t1 -(7 rows) - --- Test case where t1 can be optimized but not t2 -explain (costs off) select t1.*,t2.x,t2.z -from t1 inner join t2 on t1.a = t2.x and t1.b = t2.y -group by t1.a,t1.b,t1.c,t1.d,t2.x,t2.z; - QUERY PLAN ------------------------------------------------------- - HashAggregate - Group Key: t1.a, t1.b, t2.z - -> Hash Join - Hash Cond: ((t2.x = t1.a) AND (t2.y = t1.b)) - -> Seq Scan on t2 - -> Hash - -> Seq Scan on t1 -(7 rows) - --- Cannot optimize when PK is deferrable -explain (costs off) select * from t3 group by a,b,c; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a, b, c - -> Seq Scan on t3 -(3 rows) - -create temp table t1c () inherits (t1); --- Ensure we don't remove any columns when t1 has a child table -explain (costs off) select * from t1 group by a,b,c,d; - QUERY PLAN -------------------------------------- - HashAggregate - Group Key: t1.a, t1.b, t1.c, t1.d - -> Append - -> Seq Scan on t1 t1_1 - -> Seq Scan on t1c t1_2 -(5 rows) - --- Okay to remove columns if we're only querying the parent. -explain (costs off) select * from only t1 group by a,b,c,d; - QUERY PLAN ----------------------- - HashAggregate - Group Key: a, b - -> Seq Scan on t1 -(3 rows) - -create temp table p_t1 ( - a int, - b int, - c int, - d int, - primary key(a,b) -) partition by list(a); -create temp table p_t1_1 partition of p_t1 for values in(1); -create temp table p_t1_2 partition of p_t1 for values in(2); --- Ensure we can remove non-PK columns for partitioned tables. -explain (costs off) select * from p_t1 group by a,b,c,d; - QUERY PLAN --------------------------------- - HashAggregate - Group Key: p_t1.a, p_t1.b - -> Append - -> Seq Scan on p_t1_1 - -> Seq Scan on p_t1_2 -(5 rows) - -drop table t1 cascade; -NOTICE: drop cascades to table t1c -drop table t2; -drop table t3; -drop table p_t1; --- --- Test GROUP BY matching of join columns that are type-coerced due to USING --- -create temp table t1(f1 int, f2 int); -create temp table t2(f1 bigint, f2 oid); -select f1 from t1 left join t2 using (f1) group by f1; - f1 ----- -(0 rows) - -select f1 from t1 left join t2 using (f1) group by t1.f1; - f1 ----- -(0 rows) - -select t1.f1 from t1 left join t2 using (f1) group by t1.f1; - f1 ----- -(0 rows) - --- only this one should fail: -select t1.f1 from t1 left join t2 using (f1) group by f1; -ERROR: column "t1.f1" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: select t1.f1 from t1 left join t2 using (f1) group by f1; - ^ --- check case where we have to inject nullingrels into coerced join alias -select f1, count(*) from -t1 x(x0,x1) left join (t1 left join t2 using(f1)) on (x0 = 0) -group by f1; - f1 | count -----+------- -(0 rows) - --- same, for a RelabelType coercion -select f2, count(*) from -t1 x(x0,x1) left join (t1 left join t2 using(f2)) on (x0 = 0) -group by f2; - f2 | count -----+------- -(0 rows) - -drop table t1, t2; --- --- Test planner's selection of pathkeys for ORDER BY aggregates --- --- Ensure we order by four. This suits the most aggregate functions. -explain (costs off) -select sum(two order by two),max(four order by four), min(four order by four) -from tenk1; - QUERY PLAN -------------------------------- - Aggregate - -> Sort - Sort Key: four - -> Seq Scan on tenk1 -(4 rows) - --- Ensure we order by two. It's a tie between ordering by two and four but --- we tiebreak on the aggregate's position. -explain (costs off) -select - sum(two order by two), max(four order by four), - min(four order by four), max(two order by two) -from tenk1; - QUERY PLAN -------------------------------- - Aggregate - -> Sort - Sort Key: two - -> Seq Scan on tenk1 -(4 rows) - --- Similar to above, but tiebreak on ordering by four -explain (costs off) -select - max(four order by four), sum(two order by two), - min(four order by four), max(two order by two) -from tenk1; - QUERY PLAN -------------------------------- - Aggregate - -> Sort - Sort Key: four - -> Seq Scan on tenk1 -(4 rows) - --- Ensure this one orders by ten since there are 3 aggregates that require ten --- vs two that suit two and four. -explain (costs off) -select - max(four order by four), sum(two order by two), - min(four order by four), max(two order by two), - sum(ten order by ten), min(ten order by ten), max(ten order by ten) -from tenk1; - QUERY PLAN -------------------------------- - Aggregate - -> Sort - Sort Key: ten - -> Seq Scan on tenk1 -(4 rows) - --- Try a case involving a GROUP BY clause where the GROUP BY column is also --- part of an aggregate's ORDER BY clause. We want a sort order that works --- for the GROUP BY along with the first and the last aggregate. -explain (costs off) -select - sum(unique1 order by ten, two), sum(unique1 order by four), - sum(unique1 order by two, four) -from tenk1 -group by ten; - QUERY PLAN ----------------------------------- - GroupAggregate - Group Key: ten - -> Sort - Sort Key: ten, two, four - -> Seq Scan on tenk1 -(5 rows) - --- Ensure that we never choose to provide presorted input to an Aggref with --- a volatile function in the ORDER BY / DISTINCT clause. We want to ensure --- these sorts are performed individually rather than at the query level. -explain (costs off) -select - sum(unique1 order by two), sum(unique1 order by four), - sum(unique1 order by four, two), sum(unique1 order by two, random()), - sum(unique1 order by two, random(), random() + 1) -from tenk1 -group by ten; - QUERY PLAN ----------------------------------- - GroupAggregate - Group Key: ten - -> Sort - Sort Key: ten, four, two - -> Seq Scan on tenk1 -(5 rows) - --- Ensure consecutive NULLs are properly treated as distinct from each other -select array_agg(distinct val) -from (select null as val from generate_series(1, 2)); - array_agg ------------ - {NULL} -(1 row) - --- Ensure no ordering is requested when enable_presorted_aggregate is off -set enable_presorted_aggregate to off; -explain (costs off) -select sum(two order by two) from tenk1; - QUERY PLAN -------------------------- - Aggregate - -> Seq Scan on tenk1 -(2 rows) - -reset enable_presorted_aggregate; --- --- Test combinations of DISTINCT and/or ORDER BY --- -select array_agg(a order by b) - from (values (1,4),(2,3),(3,1),(4,2)) v(a,b); - array_agg ------------ - {3,4,2,1} -(1 row) - -select array_agg(a order by a) - from (values (1,4),(2,3),(3,1),(4,2)) v(a,b); - array_agg ------------ - {1,2,3,4} -(1 row) - -select array_agg(a order by a desc) - from (values (1,4),(2,3),(3,1),(4,2)) v(a,b); - array_agg ------------ - {4,3,2,1} -(1 row) - -select array_agg(b order by a desc) - from (values (1,4),(2,3),(3,1),(4,2)) v(a,b); - array_agg ------------ - {2,1,3,4} -(1 row) - -select array_agg(distinct a) - from (values (1),(2),(1),(3),(null),(2)) v(a); - array_agg --------------- - {1,2,3,NULL} -(1 row) - -select array_agg(distinct a order by a) - from (values (1),(2),(1),(3),(null),(2)) v(a); - array_agg --------------- - {1,2,3,NULL} -(1 row) - -select array_agg(distinct a order by a desc) - from (values (1),(2),(1),(3),(null),(2)) v(a); - array_agg --------------- - {NULL,3,2,1} -(1 row) - -select array_agg(distinct a order by a desc nulls last) - from (values (1),(2),(1),(3),(null),(2)) v(a); - array_agg --------------- - {3,2,1,NULL} -(1 row) - --- multi-arg aggs, strict/nonstrict, distinct/order by -select aggfstr(a,b,c) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c); - aggfstr ---------------------------------------- - {"(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select aggfns(a,b,c) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c); - aggfns ------------------------------------------------ - {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select aggfstr(distinct a,b,c) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,3) i; - aggfstr ---------------------------------------- - {"(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select aggfns(distinct a,b,c) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,3) i; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select aggfstr(distinct a,b,c order by b) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,3) i; - aggfstr ---------------------------------------- - {"(3,1,baz)","(2,2,bar)","(1,3,foo)"} -(1 row) - -select aggfns(distinct a,b,c order by b) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,3) i; - aggfns ------------------------------------------------ - {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} -(1 row) - --- test specific code paths -select aggfns(distinct a,a,c order by c using ~<~,a) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,2) i; - aggfns ------------------------------------------------- - {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"} -(1 row) - -select aggfns(distinct a,a,c order by c using ~<~) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,2) i; - aggfns ------------------------------------------------- - {"(2,2,bar)","(3,3,baz)","(1,1,foo)","(0,0,)"} -(1 row) - -select aggfns(distinct a,a,c order by a) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,2) i; - aggfns ------------------------------------------------- - {"(0,0,)","(1,1,foo)","(2,2,bar)","(3,3,baz)"} -(1 row) - -select aggfns(distinct a,b,c order by a,c using ~<~,b) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,2) i; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - --- test a more complex permutation that has previous caused issues -select - string_agg(distinct 'a', ','), - sum(( - select sum(1) - from (values(1)) b(id) - where a.id = b.id -)) from unnest(array[1]) a(id); - string_agg | sum -------------+----- - a | 1 -(1 row) - --- check node I/O via view creation and usage, also deparsing logic -create view agg_view1 as - select aggfns(a,b,c) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c); -select * from agg_view1; - aggfns ------------------------------------------------ - {"(1,3,foo)","(0,,)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(a, b, c) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c); -(1 row) - -create or replace view agg_view1 as - select aggfns(distinct a,b,c) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,3) i; -select * from agg_view1; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(DISTINCT v.a, v.b, v.c) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+ - generate_series(1, 3) i(i); -(1 row) - -create or replace view agg_view1 as - select aggfns(distinct a,b,c order by b) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,3) i; -select * from agg_view1; - aggfns ------------------------------------------------ - {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.b) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+ - generate_series(1, 3) i(i); -(1 row) - -create or replace view agg_view1 as - select aggfns(a,b,c order by b+1) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c); -select * from agg_view1; - aggfns ------------------------------------------------ - {"(3,1,baz)","(2,2,bar)","(1,3,foo)","(0,,)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(a, b, c ORDER BY (b + 1)) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c); -(1 row) - -create or replace view agg_view1 as - select aggfns(a,a,c order by b) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c); -select * from agg_view1; - aggfns ------------------------------------------------- - {"(3,3,baz)","(2,2,bar)","(1,1,foo)","(0,0,)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(a, a, c ORDER BY b) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c); -(1 row) - -create or replace view agg_view1 as - select aggfns(a,b,c order by c using ~<~) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c); -select * from agg_view1; - aggfns ------------------------------------------------ - {"(2,2,bar)","(3,1,baz)","(1,3,foo)","(0,,)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(a, b, c ORDER BY c USING ~<~ NULLS LAST) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c); -(1 row) - -create or replace view agg_view1 as - select aggfns(distinct a,b,c order by a,c using ~<~,b) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,2) i; -select * from agg_view1; - aggfns ------------------------------------------------ - {"(0,,)","(1,3,foo)","(2,2,bar)","(3,1,baz)"} -(1 row) - -select pg_get_viewdef('agg_view1'::regclass); - pg_get_viewdef ---------------------------------------------------------------------------------------------------------------------- - SELECT aggfns(DISTINCT v.a, v.b, v.c ORDER BY v.a, v.c USING ~<~ NULLS LAST, v.b) AS aggfns + - FROM ( VALUES (1,3,'foo'::text), (0,NULL::integer,NULL::text), (2,2,'bar'::text), (3,1,'baz'::text)) v(a, b, c),+ - generate_series(1, 2) i(i); -(1 row) - -drop view agg_view1; --- incorrect DISTINCT usage errors -select aggfns(distinct a,b,c order by i) - from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,b,c order by i) - ^ -select aggfns(distinct a,b,c order by a,b+1) - from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,b,c order by a,b+1) - ^ -select aggfns(distinct a,b,c order by a,b,i,c) - from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,b,c order by a,b,i,c) - ^ -select aggfns(distinct a,a,c order by a,b) - from (values (1,1,'foo')) v(a,b,c), generate_series(1,2) i; -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select aggfns(distinct a,a,c order by a,b) - ^ --- string_agg tests -select string_agg(a,',') from (values('aaaa'),('bbbb'),('cccc')) g(a); - string_agg ----------------- - aaaa,bbbb,cccc -(1 row) - -select string_agg(a,',') from (values('aaaa'),(null),('bbbb'),('cccc')) g(a); - string_agg ----------------- - aaaa,bbbb,cccc -(1 row) - -select string_agg(a,'AB') from (values(null),(null),('bbbb'),('cccc')) g(a); - string_agg ------------- - bbbbABcccc -(1 row) - -select string_agg(a,',') from (values(null),(null)) g(a); - string_agg ------------- - -(1 row) - --- check some implicit casting cases, as per bug #5564 -select string_agg(distinct f1, ',' order by f1) from varchar_tbl; -- ok - string_agg ------------- - a,ab,abcd -(1 row) - -select string_agg(distinct f1::text, ',' order by f1) from varchar_tbl; -- not ok -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select string_agg(distinct f1::text, ',' order by f1) from v... - ^ -select string_agg(distinct f1, ',' order by f1::text) from varchar_tbl; -- not ok -ERROR: in an aggregate with DISTINCT, ORDER BY expressions must appear in argument list -LINE 1: select string_agg(distinct f1, ',' order by f1::text) from v... - ^ -select string_agg(distinct f1::text, ',' order by f1::text) from varchar_tbl; -- ok - string_agg ------------- - a,ab,abcd -(1 row) - --- string_agg bytea tests -create table bytea_test_table(v bytea); -select string_agg(v, '') from bytea_test_table; - string_agg ------------- - -(1 row) - -insert into bytea_test_table values(decode('ff','hex')); -select string_agg(v, '') from bytea_test_table; - string_agg ------------- - \xff -(1 row) - -insert into bytea_test_table values(decode('aa','hex')); -select string_agg(v, '') from bytea_test_table; - string_agg ------------- - \xffaa -(1 row) - -select string_agg(v, NULL) from bytea_test_table; - string_agg ------------- - \xffaa -(1 row) - -select string_agg(v, decode('ee', 'hex')) from bytea_test_table; - string_agg ------------- - \xffeeaa -(1 row) - -drop table bytea_test_table; --- Test parallel string_agg and array_agg -create table pagg_test (x int, y int); -insert into pagg_test -select (case x % 4 when 1 then null else x end), x % 10 -from generate_series(1,5000) x; -set parallel_setup_cost TO 0; -set parallel_tuple_cost TO 0; -set parallel_leader_participation TO 0; -set min_parallel_table_scan_size = 0; -set bytea_output = 'escape'; -set max_parallel_workers_per_gather = 2; --- create a view as we otherwise have to repeat this query a few times. -create view v_pagg_test AS -select - y, - min(t) AS tmin,max(t) AS tmax,count(distinct t) AS tndistinct, - min(b) AS bmin,max(b) AS bmax,count(distinct b) AS bndistinct, - min(a) AS amin,max(a) AS amax,count(distinct a) AS andistinct, - min(aa) AS aamin,max(aa) AS aamax,count(distinct aa) AS aandistinct -from ( - select - y, - unnest(regexp_split_to_array(a1.t, ','))::int AS t, - unnest(regexp_split_to_array(a1.b::text, ',')) AS b, - unnest(a1.a) AS a, - unnest(a1.aa) AS aa - from ( - select - y, - string_agg(x::text, ',') AS t, - string_agg(x::text::bytea, ',') AS b, - array_agg(x) AS a, - array_agg(ARRAY[x]) AS aa - from pagg_test - group by y - ) a1 -) a2 -group by y; --- Ensure results are correct. -select * from v_pagg_test order by y; - y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ----+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- - 0 | 10 | 5000 | 500 | 10 | 990 | 500 | 10 | 5000 | 500 | 10 | 5000 | 500 - 1 | 11 | 4991 | 250 | 1011 | 991 | 250 | 11 | 4991 | 250 | 11 | 4991 | 250 - 2 | 2 | 4992 | 500 | 1002 | 992 | 500 | 2 | 4992 | 500 | 2 | 4992 | 500 - 3 | 3 | 4983 | 250 | 1003 | 983 | 250 | 3 | 4983 | 250 | 3 | 4983 | 250 - 4 | 4 | 4994 | 500 | 1004 | 994 | 500 | 4 | 4994 | 500 | 4 | 4994 | 500 - 5 | 15 | 4995 | 250 | 1015 | 995 | 250 | 15 | 4995 | 250 | 15 | 4995 | 250 - 6 | 6 | 4996 | 500 | 1006 | 996 | 500 | 6 | 4996 | 500 | 6 | 4996 | 500 - 7 | 7 | 4987 | 250 | 1007 | 987 | 250 | 7 | 4987 | 250 | 7 | 4987 | 250 - 8 | 8 | 4998 | 500 | 1008 | 998 | 500 | 8 | 4998 | 500 | 8 | 4998 | 500 - 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 -(10 rows) - --- Ensure parallel aggregation is actually being used. -explain (costs off) select * from v_pagg_test order by y; - QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------- - GroupAggregate - Group Key: pagg_test.y - -> Sort - Sort Key: pagg_test.y, (((unnest(regexp_split_to_array((string_agg((pagg_test.x)::text, ','::text)), ','::text))))::integer) - -> Result - -> ProjectSet - -> Finalize HashAggregate - Group Key: pagg_test.y - -> Gather - Workers Planned: 2 - -> Partial HashAggregate - Group Key: pagg_test.y - -> Parallel Seq Scan on pagg_test -(13 rows) - -set max_parallel_workers_per_gather = 0; --- Ensure results are the same without parallel aggregation. -select * from v_pagg_test order by y; - y | tmin | tmax | tndistinct | bmin | bmax | bndistinct | amin | amax | andistinct | aamin | aamax | aandistinct ----+------+------+------------+------+------+------------+------+------+------------+-------+-------+------------- - 0 | 10 | 5000 | 500 | 10 | 990 | 500 | 10 | 5000 | 500 | 10 | 5000 | 500 - 1 | 11 | 4991 | 250 | 1011 | 991 | 250 | 11 | 4991 | 250 | 11 | 4991 | 250 - 2 | 2 | 4992 | 500 | 1002 | 992 | 500 | 2 | 4992 | 500 | 2 | 4992 | 500 - 3 | 3 | 4983 | 250 | 1003 | 983 | 250 | 3 | 4983 | 250 | 3 | 4983 | 250 - 4 | 4 | 4994 | 500 | 1004 | 994 | 500 | 4 | 4994 | 500 | 4 | 4994 | 500 - 5 | 15 | 4995 | 250 | 1015 | 995 | 250 | 15 | 4995 | 250 | 15 | 4995 | 250 - 6 | 6 | 4996 | 500 | 1006 | 996 | 500 | 6 | 4996 | 500 | 6 | 4996 | 500 - 7 | 7 | 4987 | 250 | 1007 | 987 | 250 | 7 | 4987 | 250 | 7 | 4987 | 250 - 8 | 8 | 4998 | 500 | 1008 | 998 | 500 | 8 | 4998 | 500 | 8 | 4998 | 500 - 9 | 19 | 4999 | 250 | 1019 | 999 | 250 | 19 | 4999 | 250 | 19 | 4999 | 250 -(10 rows) - --- Clean up -reset max_parallel_workers_per_gather; -reset bytea_output; -reset min_parallel_table_scan_size; -reset parallel_leader_participation; -reset parallel_tuple_cost; -reset parallel_setup_cost; -drop view v_pagg_test; -drop table pagg_test; --- FILTER tests -select min(unique1) filter (where unique1 > 100) from tenk1; - min ------ - 101 -(1 row) - -select sum(1/ten) filter (where ten > 0) from tenk1; - sum ------- - 1000 -(1 row) - -select ten, sum(distinct four) filter (where four::text ~ '123') from onek a -group by ten; - ten | sum ------+----- - 0 | - 1 | - 2 | - 3 | - 4 | - 5 | - 6 | - 7 | - 8 | - 9 | -(10 rows) - -select ten, sum(distinct four) filter (where four > 10) from onek a -group by ten -having exists (select 1 from onek b where sum(distinct a.four) = b.four); - ten | sum ------+----- - 0 | - 2 | - 4 | - 6 | - 8 | -(5 rows) - -select max(foo COLLATE "C") filter (where (bar collate "POSIX") > '0') -from (values ('a', 'b')) AS v(foo,bar); - max ------ - a -(1 row) - -select any_value(v) filter (where v > 2) from (values (1), (2), (3)) as v (v); - any_value ------------ - 3 -(1 row) - --- outer reference in FILTER (PostgreSQL extension) -select (select count(*) - from (values (1)) t0(inner_c)) -from (values (2),(3)) t1(outer_c); -- inner query is aggregation query - count -------- - 1 - 1 -(2 rows) - -select (select count(*) filter (where outer_c <> 0) - from (values (1)) t0(inner_c)) -from (values (2),(3)) t1(outer_c); -- outer query is aggregation query - count -------- - 2 -(1 row) - -select (select count(inner_c) filter (where outer_c <> 0) - from (values (1)) t0(inner_c)) -from (values (2),(3)) t1(outer_c); -- inner query is aggregation query - count -------- - 1 - 1 -(2 rows) - -select - (select max((select i.unique2 from tenk1 i where i.unique1 = o.unique1)) - filter (where o.unique1 < 10)) -from tenk1 o; -- outer query is aggregation query - max ------- - 9998 -(1 row) - --- subquery in FILTER clause (PostgreSQL extension) -select sum(unique1) FILTER (WHERE - unique1 IN (SELECT unique1 FROM onek where unique1 < 100)) FROM tenk1; - sum ------- - 4950 -(1 row) - --- exercise lots of aggregate parts with FILTER -select aggfns(distinct a,b,c order by a,c using ~<~,b) filter (where a > 1) - from (values (1,3,'foo'),(0,null,null),(2,2,'bar'),(3,1,'baz')) v(a,b,c), - generate_series(1,2) i; - aggfns ---------------------------- - {"(2,2,bar)","(3,1,baz)"} -(1 row) - --- check handling of bare boolean Var in FILTER -select max(0) filter (where b1) from bool_test; - max ------ - 0 -(1 row) - -select (select max(0) filter (where b1)) from bool_test; - max ------ - 0 -(1 row) - --- check for correct detection of nested-aggregate errors in FILTER -select max(unique1) filter (where sum(ten) > 0) from tenk1; -ERROR: aggregate functions are not allowed in FILTER -LINE 1: select max(unique1) filter (where sum(ten) > 0) from tenk1; - ^ -select (select max(unique1) filter (where sum(ten) > 0) from int8_tbl) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select (select max(unique1) filter (where sum(ten) > 0) from... - ^ -select max(unique1) filter (where bool_or(ten > 0)) from tenk1; -ERROR: aggregate functions are not allowed in FILTER -LINE 1: select max(unique1) filter (where bool_or(ten > 0)) from ten... - ^ -select (select max(unique1) filter (where bool_or(ten > 0)) from int8_tbl) from tenk1; -ERROR: aggregate function calls cannot be nested -LINE 1: select (select max(unique1) filter (where bool_or(ten > 0)) ... - ^ --- ordered-set aggregates -select p, percentile_cont(p) within group (order by x::float8) -from generate_series(1,5) x, - (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p) -group by p order by p; - p | percentile_cont -------+----------------- - 0 | 1 - 0.1 | 1.4 - 0.25 | 2 - 0.4 | 2.6 - 0.5 | 3 - 0.6 | 3.4 - 0.75 | 4 - 0.9 | 4.6 - 1 | 5 -(9 rows) - -select p, percentile_cont(p order by p) within group (order by x) -- error -from generate_series(1,5) x, - (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p) -group by p order by p; -ERROR: cannot use multiple ORDER BY clauses with WITHIN GROUP -LINE 1: select p, percentile_cont(p order by p) within group (order ... - ^ -select p, sum() within group (order by x::float8) -- error -from generate_series(1,5) x, - (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p) -group by p order by p; -ERROR: sum is not an ordered-set aggregate, so it cannot have WITHIN GROUP -LINE 1: select p, sum() within group (order by x::float8) -- error - ^ -select p, percentile_cont(p,p) -- error -from generate_series(1,5) x, - (values (0::float8),(0.1),(0.25),(0.4),(0.5),(0.6),(0.75),(0.9),(1)) v(p) -group by p order by p; -ERROR: WITHIN GROUP is required for ordered-set aggregate percentile_cont -LINE 1: select p, percentile_cont(p,p) -- error - ^ -select percentile_cont(0.5) within group (order by b) from aggtest; - percentile_cont ------------------- - 53.4485001564026 -(1 row) - -select percentile_cont(0.5) within group (order by b), sum(b) from aggtest; - percentile_cont | sum -------------------+--------- - 53.4485001564026 | 431.773 -(1 row) - -select percentile_cont(0.5) within group (order by thousand) from tenk1; - percentile_cont ------------------ - 499.5 -(1 row) - -select percentile_disc(0.5) within group (order by thousand) from tenk1; - percentile_disc ------------------ - 499 -(1 row) - -select rank(3) within group (order by x) -from (values (1),(1),(2),(2),(3),(3),(4)) v(x); - rank ------- - 5 -(1 row) - -select cume_dist(3) within group (order by x) -from (values (1),(1),(2),(2),(3),(3),(4)) v(x); - cume_dist ------------ - 0.875 -(1 row) - -select percent_rank(3) within group (order by x) -from (values (1),(1),(2),(2),(3),(3),(4),(5)) v(x); - percent_rank --------------- - 0.5 -(1 row) - -select dense_rank(3) within group (order by x) -from (values (1),(1),(2),(2),(3),(3),(4)) v(x); - dense_rank ------------- - 3 -(1 row) - -select percentile_disc(array[0,0.1,0.25,0.5,0.75,0.9,1]) within group (order by thousand) -from tenk1; - percentile_disc ----------------------------- - {0,99,249,499,749,899,999} -(1 row) - -select percentile_cont(array[0,0.25,0.5,0.75,1]) within group (order by thousand) -from tenk1; - percentile_cont ------------------------------ - {0,249.75,499.5,749.25,999} -(1 row) - -select percentile_disc(array[[null,1,0.5],[0.75,0.25,null]]) within group (order by thousand) -from tenk1; - percentile_disc ---------------------------------- - {{NULL,999,499},{749,249,NULL}} -(1 row) - -select percentile_cont(array[0,1,0.25,0.75,0.5,1,0.3,0.32,0.35,0.38,0.4]) within group (order by x) -from generate_series(1,6) x; - percentile_cont ------------------------------------------- - {1,6,2.25,4.75,3.5,6,2.5,2.6,2.75,2.9,3} -(1 row) - -select ten, mode() within group (order by string4) from tenk1 group by ten; - ten | mode ------+-------- - 0 | HHHHxx - 1 | OOOOxx - 2 | VVVVxx - 3 | OOOOxx - 4 | HHHHxx - 5 | HHHHxx - 6 | OOOOxx - 7 | AAAAxx - 8 | VVVVxx - 9 | VVVVxx -(10 rows) - -select percentile_disc(array[0.25,0.5,0.75]) within group (order by x) -from unnest('{fred,jim,fred,jack,jill,fred,jill,jim,jim,sheila,jim,sheila}'::text[]) u(x); - percentile_disc ------------------ - {fred,jill,jim} -(1 row) - --- check collation propagates up in suitable cases: -select pg_collation_for(percentile_disc(1) within group (order by x collate "POSIX")) - from (values ('fred'),('jim')) v(x); - pg_collation_for ------------------- - "POSIX" -(1 row) - --- ordered-set aggs created with CREATE AGGREGATE -select test_rank(3) within group (order by x) -from (values (1),(1),(2),(2),(3),(3),(4)) v(x); - test_rank ------------ - 5 -(1 row) - -select test_percentile_disc(0.5) within group (order by thousand) from tenk1; - test_percentile_disc ----------------------- - 499 -(1 row) - --- ordered-set aggs can't use ungrouped vars in direct args: -select rank(x) within group (order by x) from generate_series(1,5) x; -ERROR: column "x.x" must appear in the GROUP BY clause or be used in an aggregate function -LINE 1: select rank(x) within group (order by x) from generate_serie... - ^ -DETAIL: Direct arguments of an ordered-set aggregate must use only grouped columns. --- outer-level agg can't use a grouped arg of a lower level, either: -select array(select percentile_disc(a) within group (order by x) - from (values (0.3),(0.7)) v(a) group by a) - from generate_series(1,5) g(x); -ERROR: outer-level aggregate cannot contain a lower-level variable in its direct arguments -LINE 1: select array(select percentile_disc(a) within group (order b... - ^ --- agg in the direct args is a grouping violation, too: -select rank(sum(x)) within group (order by x) from generate_series(1,5) x; -ERROR: aggregate function calls cannot be nested -LINE 1: select rank(sum(x)) within group (order by x) from generate_... - ^ --- hypothetical-set type unification and argument-count failures: -select rank(3) within group (order by x) from (values ('fred'),('jim')) v(x); -ERROR: WITHIN GROUP types text and integer cannot be matched -LINE 1: select rank(3) within group (order by x) from (values ('fred... - ^ -select rank(3) within group (order by stringu1,stringu2) from tenk1; -ERROR: function rank(integer, name, name) does not exist -LINE 1: select rank(3) within group (order by stringu1,stringu2) fro... - ^ -HINT: To use the hypothetical-set aggregate rank, the number of hypothetical direct arguments (here 1) must match the number of ordering columns (here 2). -select rank('fred') within group (order by x) from generate_series(1,5) x; -ERROR: invalid input syntax for type integer: "fred" -LINE 1: select rank('fred') within group (order by x) from generate_... - ^ -select rank('adam'::text collate "C") within group (order by x collate "POSIX") - from (values ('fred'),('jim')) v(x); -ERROR: collation mismatch between explicit collations "C" and "POSIX" -LINE 1: ...adam'::text collate "C") within group (order by x collate "P... - ^ --- hypothetical-set type unification successes: -select rank('adam'::varchar) within group (order by x) from (values ('fred'),('jim')) v(x); - rank ------- - 1 -(1 row) - -select rank('3') within group (order by x) from generate_series(1,5) x; - rank ------- - 3 -(1 row) - --- divide by zero check -select percent_rank(0) within group (order by x) from generate_series(1,0) x; - percent_rank --------------- - 0 -(1 row) - --- deparse and multiple features: -create view aggordview1 as -select ten, - percentile_disc(0.5) within group (order by thousand) as p50, - percentile_disc(0.5) within group (order by thousand) filter (where hundred=1) as px, - rank(5,'AZZZZ',50) within group (order by hundred, string4 desc, hundred) - from tenk1 - group by ten order by ten; -select pg_get_viewdef('aggordview1'); - pg_get_viewdef -------------------------------------------------------------------------------------------------------------------- - SELECT ten, + - percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY thousand) AS p50, + - percentile_disc((0.5)::double precision) WITHIN GROUP (ORDER BY thousand) FILTER (WHERE (hundred = 1)) AS px,+ - rank(5, 'AZZZZ'::name, 50) WITHIN GROUP (ORDER BY hundred, string4 DESC, hundred) AS rank + - FROM tenk1 + - GROUP BY ten + - ORDER BY ten; -(1 row) - -select * from aggordview1 order by ten; - ten | p50 | px | rank ------+-----+-----+------ - 0 | 490 | | 101 - 1 | 491 | 401 | 101 - 2 | 492 | | 101 - 3 | 493 | | 101 - 4 | 494 | | 101 - 5 | 495 | | 67 - 6 | 496 | | 1 - 7 | 497 | | 1 - 8 | 498 | | 1 - 9 | 499 | | 1 -(10 rows) - -drop view aggordview1; --- variadic aggregates -select least_agg(q1,q2) from int8_tbl; - least_agg -------------------- - -4567890123456789 -(1 row) - -select least_agg(variadic array[q1,q2]) from int8_tbl; - least_agg -------------------- - -4567890123456789 -(1 row) - -select cleast_agg(q1,q2) from int8_tbl; - cleast_agg -------------------- - -4567890123456789 -(1 row) - -select cleast_agg(4.5,f1) from int4_tbl; - cleast_agg -------------- - -2147483647 -(1 row) - -select cleast_agg(variadic array[4.5,f1]) from int4_tbl; - cleast_agg -------------- - -2147483647 -(1 row) - -select pg_typeof(cleast_agg(variadic array[4.5,f1])) from int4_tbl; - pg_typeof ------------ - numeric -(1 row) - --- test aggregates with common transition functions share the same states -begin work; -create type avg_state as (total bigint, count bigint); -create or replace function avg_transfn(state avg_state, n int) returns avg_state as -$$ -declare new_state avg_state; -begin - raise notice 'avg_transfn called with %', n; - if state is null then - if n is not null then - new_state.total := n; - new_state.count := 1; - return new_state; - end if; - return null; - elsif n is not null then - state.total := state.total + n; - state.count := state.count + 1; - return state; - end if; - - return null; -end -$$ language plpgsql; -create function avg_finalfn(state avg_state) returns int4 as -$$ -begin - if state is null then - return NULL; - else - return state.total / state.count; - end if; -end -$$ language plpgsql; -create function sum_finalfn(state avg_state) returns int4 as -$$ -begin - if state is null then - return NULL; - else - return state.total; - end if; -end -$$ language plpgsql; -create aggregate my_avg(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = avg_finalfn -); -create aggregate my_sum(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = sum_finalfn -); --- aggregate state should be shared as aggs are the same. -select my_avg(one),my_avg(one) from (values(1),(3)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_avg ---------+-------- - 2 | 2 -(1 row) - --- aggregate state should be shared as transfn is the same for both aggs. -select my_avg(one),my_sum(one) from (values(1),(3)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 4 -(1 row) - --- same as previous one, but with DISTINCT, which requires sorting the input. -select my_avg(distinct one),my_sum(distinct one) from (values(1),(3),(1)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 4 -(1 row) - --- shouldn't share states due to the distinctness not matching. -select my_avg(distinct one),my_sum(one) from (values(1),(3)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 2 | 4 -(1 row) - --- shouldn't share states due to the filter clause not matching. -select my_avg(one) filter (where one > 1),my_sum(one) from (values(1),(3)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 3 - my_avg | my_sum ---------+-------- - 3 | 4 -(1 row) - --- this should not share the state due to different input columns. -select my_avg(one),my_sum(two) from (values(1,2),(3,4)) t(one,two); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 2 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 4 - my_avg | my_sum ---------+-------- - 2 | 6 -(1 row) - --- exercise cases where OSAs share state -select - percentile_cont(0.5) within group (order by a), - percentile_disc(0.5) within group (order by a) -from (values(1::float8),(3),(5),(7)) t(a); - percentile_cont | percentile_disc ------------------+----------------- - 4 | 3 -(1 row) - -select - percentile_cont(0.25) within group (order by a), - percentile_disc(0.5) within group (order by a) -from (values(1::float8),(3),(5),(7)) t(a); - percentile_cont | percentile_disc ------------------+----------------- - 2.5 | 3 -(1 row) - --- these can't share state currently -select - rank(4) within group (order by a), - dense_rank(4) within group (order by a) -from (values(1),(3),(5),(7)) t(a); - rank | dense_rank -------+------------ - 3 | 3 -(1 row) - --- test that aggs with the same sfunc and initcond share the same agg state -create aggregate my_sum_init(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = sum_finalfn, - initcond = '(10,0)' -); -create aggregate my_avg_init(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = avg_finalfn, - initcond = '(10,0)' -); -create aggregate my_avg_init2(int4) -( - stype = avg_state, - sfunc = avg_transfn, - finalfunc = avg_finalfn, - initcond = '(4,0)' -); --- state should be shared if INITCONDs are matching -select my_sum_init(one),my_avg_init(one) from (values(1),(3)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 - my_sum_init | my_avg_init --------------+------------- - 14 | 7 -(1 row) - --- Varying INITCONDs should cause the states not to be shared. -select my_sum_init(one),my_avg_init2(one) from (values(1),(3)) t(one); -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 1 -NOTICE: avg_transfn called with 3 -NOTICE: avg_transfn called with 3 - my_sum_init | my_avg_init2 --------------+-------------- - 14 | 4 -(1 row) - -rollback; --- test aggregate state sharing to ensure it works if one aggregate has a --- finalfn and the other one has none. -begin work; -create or replace function sum_transfn(state int4, n int4) returns int4 as -$$ -declare new_state int4; -begin - raise notice 'sum_transfn called with %', n; - if state is null then - if n is not null then - new_state := n; - return new_state; - end if; - return null; - elsif n is not null then - state := state + n; - return state; - end if; - - return null; -end -$$ language plpgsql; -create function halfsum_finalfn(state int4) returns int4 as -$$ -begin - if state is null then - return NULL; - else - return state / 2; - end if; -end -$$ language plpgsql; -create aggregate my_sum(int4) -( - stype = int4, - sfunc = sum_transfn -); -create aggregate my_half_sum(int4) -( - stype = int4, - sfunc = sum_transfn, - finalfunc = halfsum_finalfn -); --- Agg state should be shared even though my_sum has no finalfn -select my_sum(one),my_half_sum(one) from (values(1),(2),(3),(4)) t(one); -NOTICE: sum_transfn called with 1 -NOTICE: sum_transfn called with 2 -NOTICE: sum_transfn called with 3 -NOTICE: sum_transfn called with 4 - my_sum | my_half_sum ---------+------------- - 10 | 5 -(1 row) - -rollback; --- test that the aggregate transition logic correctly handles --- transition / combine functions returning NULL --- First test the case of a normal transition function returning NULL -BEGIN; -CREATE FUNCTION balkifnull(int8, int4) -RETURNS int8 -STRICT -LANGUAGE plpgsql AS $$ -BEGIN - IF $1 IS NULL THEN - RAISE 'erroneously called with NULL argument'; - END IF; - RETURN NULL; -END$$; -CREATE AGGREGATE balk(int4) -( - SFUNC = balkifnull(int8, int4), - STYPE = int8, - PARALLEL = SAFE, - INITCOND = '0' -); -SELECT balk(hundred) FROM tenk1; - balk ------- - -(1 row) - -ROLLBACK; --- GROUP BY optimization by reordering GROUP BY clauses -CREATE TABLE btg AS SELECT - i % 10 AS x, - i % 10 AS y, - 'abc' || i % 10 AS z, - i AS w -FROM generate_series(1, 100) AS i; -CREATE INDEX btg_x_y_idx ON btg(x, y); -ANALYZE btg; -SET enable_hashagg = off; -SET enable_seqscan = off; --- Utilize the ordering of index scan to avoid a Sort operation -EXPLAIN (COSTS OFF) -SELECT count(*) FROM btg GROUP BY y, x; - QUERY PLAN ------------------------------------------------- - GroupAggregate - Group Key: x, y - -> Index Only Scan using btg_x_y_idx on btg -(3 rows) - --- Engage incremental sort -EXPLAIN (COSTS OFF) -SELECT count(*) FROM btg GROUP BY z, y, w, x; - QUERY PLAN -------------------------------------------------- - GroupAggregate - Group Key: x, y, z, w - -> Incremental Sort - Sort Key: x, y, z, w - Presorted Key: x, y - -> Index Scan using btg_x_y_idx on btg -(6 rows) - --- Utilize the ordering of subquery scan to avoid a Sort operation -EXPLAIN (COSTS OFF) SELECT count(*) -FROM (SELECT * FROM btg ORDER BY x, y, w, z) AS q1 -GROUP BY w, x, z, y; - QUERY PLAN -------------------------------------------------- - GroupAggregate - Group Key: btg.x, btg.y, btg.w, btg.z - -> Incremental Sort - Sort Key: btg.x, btg.y, btg.w, btg.z - Presorted Key: btg.x, btg.y - -> Index Scan using btg_x_y_idx on btg -(6 rows) - --- Utilize the ordering of merge join to avoid a full Sort operation -SET enable_hashjoin = off; -SET enable_nestloop = off; -EXPLAIN (COSTS OFF) -SELECT count(*) - FROM btg t1 JOIN btg t2 ON t1.z = t2.z AND t1.w = t2.w AND t1.x = t2.x - GROUP BY t1.x, t1.y, t1.z, t1.w; - QUERY PLAN -------------------------------------------------------------------------------- - GroupAggregate - Group Key: t1.z, t1.w, t1.x, t1.y - -> Incremental Sort - Sort Key: t1.z, t1.w, t1.x, t1.y - Presorted Key: t1.z, t1.w, t1.x - -> Merge Join - Merge Cond: ((t1.z = t2.z) AND (t1.w = t2.w) AND (t1.x = t2.x)) - -> Sort - Sort Key: t1.z, t1.w, t1.x - -> Index Scan using btg_x_y_idx on btg t1 - -> Sort - Sort Key: t2.z, t2.w, t2.x - -> Index Scan using btg_x_y_idx on btg t2 -(13 rows) - -RESET enable_nestloop; -RESET enable_hashjoin; --- Should work with and without GROUP-BY optimization -EXPLAIN (COSTS OFF) -SELECT count(*) FROM btg GROUP BY w, x, z, y ORDER BY y, x, z, w; - QUERY PLAN -------------------------------------------------- - GroupAggregate - Group Key: y, x, z, w - -> Sort - Sort Key: y, x, z, w - -> Index Scan using btg_x_y_idx on btg -(5 rows) - --- Utilize incremental sort to make the ORDER BY rule a bit cheaper -EXPLAIN (COSTS OFF) -SELECT count(*) FROM btg GROUP BY w, x, y, z ORDER BY x*x, z; - QUERY PLAN -------------------------------------------------------- - Sort - Sort Key: ((x * x)), z - -> GroupAggregate - Group Key: x, y, w, z - -> Incremental Sort - Sort Key: x, y, w, z - Presorted Key: x, y - -> Index Scan using btg_x_y_idx on btg -(8 rows) - --- Test the case where the number of incoming subtree path keys is more than --- the number of grouping keys. -CREATE INDEX btg_y_x_w_idx ON btg(y, x, w); -EXPLAIN (VERBOSE, COSTS OFF) -SELECT y, x, array_agg(distinct w) - FROM btg WHERE y < 0 GROUP BY x, y; - QUERY PLAN ---------------------------------------------------------- - GroupAggregate - Output: y, x, array_agg(DISTINCT w) - Group Key: btg.y, btg.x - -> Index Only Scan using btg_y_x_w_idx on public.btg - Output: y, x, w - Index Cond: (btg.y < 0) -(6 rows) - --- Ensure that we do not select the aggregate pathkeys instead of the grouping --- pathkeys -CREATE TABLE group_agg_pk AS SELECT - i % 10 AS x, - i % 2 AS y, - i % 2 AS z, - 2 AS w, - i % 10 AS f -FROM generate_series(1,100) AS i; -ANALYZE group_agg_pk; -SET enable_nestloop = off; -SET enable_hashjoin = off; -EXPLAIN (COSTS OFF) -SELECT avg(c1.f ORDER BY c1.x, c1.y) -FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x -GROUP BY c1.w, c1.z; - QUERY PLAN ------------------------------------------------------ - GroupAggregate - Group Key: c1.w, c1.z - -> Sort - Sort Key: c1.w, c1.z, c1.x, c1.y - -> Merge Join - Merge Cond: (c1.x = c2.x) - -> Sort - Sort Key: c1.x - -> Seq Scan on group_agg_pk c1 - -> Sort - Sort Key: c2.x - -> Seq Scan on group_agg_pk c2 -(12 rows) - -SELECT avg(c1.f ORDER BY c1.x, c1.y) -FROM group_agg_pk c1 JOIN group_agg_pk c2 ON c1.x = c2.x -GROUP BY c1.w, c1.z; - avg --------------------- - 4.0000000000000000 - 5.0000000000000000 -(2 rows) - -RESET enable_nestloop; -RESET enable_hashjoin; -DROP TABLE group_agg_pk; --- Test the case where the the ordering of scan matches the ordering within the --- aggregate but cannot be found in the group-by list -CREATE TABLE agg_sort_order (c1 int PRIMARY KEY, c2 int); -CREATE UNIQUE INDEX agg_sort_order_c2_idx ON agg_sort_order(c2); -INSERT INTO agg_sort_order SELECT i, i FROM generate_series(1,100)i; -ANALYZE agg_sort_order; -EXPLAIN (COSTS OFF) -SELECT array_agg(c1 ORDER BY c2),c2 -FROM agg_sort_order WHERE c2 < 100 GROUP BY c1 ORDER BY 2; - QUERY PLAN ----------------------------------------------------------------------------- - Sort - Sort Key: c2 - -> GroupAggregate - Group Key: c1 - -> Sort - Sort Key: c1, c2 - -> Index Scan using agg_sort_order_c2_idx on agg_sort_order - Index Cond: (c2 < 100) -(8 rows) - -DROP TABLE agg_sort_order CASCADE; -DROP TABLE btg; -RESET enable_hashagg; -RESET enable_seqscan; --- Secondly test the case of a parallel aggregate combiner function --- returning NULL. For that use normal transition function, but a --- combiner function returning NULL. -BEGIN; -CREATE FUNCTION balkifnull(int8, int8) -RETURNS int8 -PARALLEL SAFE -STRICT -LANGUAGE plpgsql AS $$ -BEGIN - IF $1 IS NULL THEN - RAISE 'erroneously called with NULL argument'; - END IF; - RETURN NULL; -END$$; -CREATE AGGREGATE balk(int4) -( - SFUNC = int4_sum(int8, int4), - STYPE = int8, - COMBINEFUNC = balkifnull(int8, int8), - PARALLEL = SAFE, - INITCOND = '0' -); --- force use of parallelism -ALTER TABLE tenk1 set (parallel_workers = 4); -SET LOCAL parallel_setup_cost=0; -SET LOCAL max_parallel_workers_per_gather=4; -EXPLAIN (COSTS OFF) SELECT balk(hundred) FROM tenk1; - QUERY PLAN -------------------------------------------------------------------------- - Finalize Aggregate - -> Gather - Workers Planned: 4 - -> Partial Aggregate - -> Parallel Index Only Scan using tenk1_hundred on tenk1 -(5 rows) - -SELECT balk(hundred) FROM tenk1; - balk ------- - -(1 row) - -ROLLBACK; --- test multiple usage of an aggregate whose finalfn returns a R/W datum -BEGIN; -CREATE FUNCTION rwagg_sfunc(x anyarray, y anyarray) RETURNS anyarray -LANGUAGE plpgsql IMMUTABLE AS $$ -BEGIN - RETURN array_fill(y[1], ARRAY[4]); -END; -$$; -CREATE FUNCTION rwagg_finalfunc(x anyarray) RETURNS anyarray -LANGUAGE plpgsql STRICT IMMUTABLE AS $$ -DECLARE - res x%TYPE; -BEGIN - -- assignment is essential for this test, it expands the array to R/W - res := array_fill(x[1], ARRAY[4]); - RETURN res; -END; -$$; -CREATE AGGREGATE rwagg(anyarray) ( - STYPE = anyarray, - SFUNC = rwagg_sfunc, - FINALFUNC = rwagg_finalfunc -); -CREATE FUNCTION eatarray(x real[]) RETURNS real[] -LANGUAGE plpgsql STRICT IMMUTABLE AS $$ -BEGIN - x[1] := x[1] + 1; - RETURN x; -END; -$$; -SELECT eatarray(rwagg(ARRAY[1.0::real])), eatarray(rwagg(ARRAY[1.0::real])); - eatarray | eatarray ------------+----------- - {2,1,1,1} | {2,1,1,1} -(1 row) - -ROLLBACK; --- test coverage for aggregate combine/serial/deserial functions -BEGIN; -SET parallel_setup_cost = 0; -SET parallel_tuple_cost = 0; -SET min_parallel_table_scan_size = 0; -SET max_parallel_workers_per_gather = 4; -SET parallel_leader_participation = off; -SET enable_indexonlyscan = off; --- variance(int4) covers numeric_poly_combine --- sum(int8) covers int8_avg_combine --- regr_count(float8, float8) covers int8inc_float8_float8 and aggregates with > 1 arg -EXPLAIN (COSTS OFF, VERBOSE) -SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - Finalize Aggregate - Output: variance(tenk1.unique1), sum((tenk1.unique1)::bigint), regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision) - -> Gather - Output: (PARTIAL variance(tenk1.unique1)), (PARTIAL sum((tenk1.unique1)::bigint)), (PARTIAL regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision)) - Workers Planned: 4 - -> Partial Aggregate - Output: PARTIAL variance(tenk1.unique1), PARTIAL sum((tenk1.unique1)::bigint), PARTIAL regr_count((tenk1.unique1)::double precision, (tenk1.unique1)::double precision) - -> Parallel Append - -> Parallel Seq Scan on public.tenk1 - Output: tenk1.unique1 - -> Parallel Seq Scan on public.tenk1 tenk1_1 - Output: tenk1_1.unique1 - -> Parallel Seq Scan on public.tenk1 tenk1_2 - Output: tenk1_2.unique1 - -> Parallel Seq Scan on public.tenk1 tenk1_3 - Output: tenk1_3.unique1 -(16 rows) - -SELECT variance(unique1::int4), sum(unique1::int8), regr_count(unique1::float8, unique1::float8) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - variance | sum | regr_count -----------------------+-----------+------------ - 8333541.588539713493 | 199980000 | 40000 -(1 row) - --- variance(int8) covers numeric_combine --- avg(numeric) covers numeric_avg_combine -EXPLAIN (COSTS OFF, VERBOSE) -SELECT variance(unique1::int8), avg(unique1::numeric) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - QUERY PLAN --------------------------------------------------------------------------------------------------------- - Finalize Aggregate - Output: variance((tenk1.unique1)::bigint), avg((tenk1.unique1)::numeric) - -> Gather - Output: (PARTIAL variance((tenk1.unique1)::bigint)), (PARTIAL avg((tenk1.unique1)::numeric)) - Workers Planned: 4 - -> Partial Aggregate - Output: PARTIAL variance((tenk1.unique1)::bigint), PARTIAL avg((tenk1.unique1)::numeric) - -> Parallel Append - -> Parallel Seq Scan on public.tenk1 - Output: tenk1.unique1 - -> Parallel Seq Scan on public.tenk1 tenk1_1 - Output: tenk1_1.unique1 - -> Parallel Seq Scan on public.tenk1 tenk1_2 - Output: tenk1_2.unique1 - -> Parallel Seq Scan on public.tenk1 tenk1_3 - Output: tenk1_3.unique1 -(16 rows) - -SELECT variance(unique1::int8), avg(unique1::numeric) -FROM (SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1 - UNION ALL SELECT * FROM tenk1) u; - variance | avg -----------------------+----------------------- - 8333541.588539713493 | 4999.5000000000000000 -(1 row) - -ROLLBACK; --- test coverage for dense_rank -SELECT dense_rank(x) WITHIN GROUP (ORDER BY x) FROM (VALUES (1),(1),(2),(2),(3),(3)) v(x) GROUP BY (x) ORDER BY 1; - dense_rank ------------- - 1 - 1 - 1 -(3 rows) - --- Ensure that the STRICT checks for aggregates does not take NULLness --- of ORDER BY columns into account. See bug report around --- 2a505161-2727-2473-7c46-591ed108ac52@email.cz -SELECT min(x ORDER BY y) FROM (VALUES(1, NULL)) AS d(x,y); - min ------ - 1 -(1 row) - -SELECT min(x ORDER BY y) FROM (VALUES(1, 2)) AS d(x,y); - min ------ - 1 -(1 row) - --- check collation-sensitive matching between grouping expressions -select v||'a', case v||'a' when 'aa' then 1 else 0 end, count(*) - from unnest(array['a','b']) u(v) - group by v||'a' order by 1; - ?column? | case | count -----------+------+------- - aa | 1 | 1 - ba | 0 | 1 -(2 rows) - -select v||'a', case when v||'a' = 'aa' then 1 else 0 end, count(*) - from unnest(array['a','b']) u(v) - group by v||'a' order by 1; - ?column? | case | count -----------+------+------- - aa | 1 | 1 - ba | 0 | 1 -(2 rows) - --- Make sure that generation of HashAggregate for uniqification purposes --- does not lead to array overflow due to unexpected duplicate hash keys --- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com -set enable_memoize to off; -explain (costs off) - select 1 from tenk1 - where (hundred, thousand) in (select twothousand, twothousand from onek); - QUERY PLAN -------------------------------------------------------------- - Hash Join - Hash Cond: (tenk1.hundred = onek.twothousand) - -> Seq Scan on tenk1 - Filter: (hundred = thousand) - -> Hash - -> HashAggregate - Group Key: onek.twothousand, onek.twothousand - -> Seq Scan on onek -(8 rows) - -reset enable_memoize; --- --- Hash Aggregation Spill tests --- -set enable_sort=false; -set work_mem='64kB'; -select unique1, count(*), sum(twothousand) from tenk1 -group by unique1 -having sum(fivethous) > 4975 -order by sum(twothousand); - unique1 | count | sum ----------+-------+------ - 4976 | 1 | 976 - 4977 | 1 | 977 - 4978 | 1 | 978 - 4979 | 1 | 979 - 4980 | 1 | 980 - 4981 | 1 | 981 - 4982 | 1 | 982 - 4983 | 1 | 983 - 4984 | 1 | 984 - 4985 | 1 | 985 - 4986 | 1 | 986 - 4987 | 1 | 987 - 4988 | 1 | 988 - 4989 | 1 | 989 - 4990 | 1 | 990 - 4991 | 1 | 991 - 4992 | 1 | 992 - 4993 | 1 | 993 - 4994 | 1 | 994 - 4995 | 1 | 995 - 4996 | 1 | 996 - 4997 | 1 | 997 - 4998 | 1 | 998 - 4999 | 1 | 999 - 9976 | 1 | 1976 - 9977 | 1 | 1977 - 9978 | 1 | 1978 - 9979 | 1 | 1979 - 9980 | 1 | 1980 - 9981 | 1 | 1981 - 9982 | 1 | 1982 - 9983 | 1 | 1983 - 9984 | 1 | 1984 - 9985 | 1 | 1985 - 9986 | 1 | 1986 - 9987 | 1 | 1987 - 9988 | 1 | 1988 - 9989 | 1 | 1989 - 9990 | 1 | 1990 - 9991 | 1 | 1991 - 9992 | 1 | 1992 - 9993 | 1 | 1993 - 9994 | 1 | 1994 - 9995 | 1 | 1995 - 9996 | 1 | 1996 - 9997 | 1 | 1997 - 9998 | 1 | 1998 - 9999 | 1 | 1999 -(48 rows) - -set work_mem to default; -set enable_sort to default; --- --- Compare results between plans using sorting and plans using hash --- aggregation. Force spilling in both cases by setting work_mem low. --- -set work_mem='64kB'; -create table agg_data_2k as -select g from generate_series(0, 1999) g; -analyze agg_data_2k; -create table agg_data_20k as -select g from generate_series(0, 19999) g; -analyze agg_data_20k; --- Produce results with sorting. -set enable_hashagg = false; -set jit_above_cost = 0; -explain (costs off) -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; - QUERY PLAN --------------------------------------- - GroupAggregate - Group Key: ((g % 10000)) - -> Sort - Sort Key: ((g % 10000)) - -> Seq Scan on agg_data_20k -(5 rows) - -create table agg_group_1 as -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; -create table agg_group_2 as -select * from - (values (100), (300), (500)) as r(a), - lateral ( - select (g/2)::numeric as c1, - array_agg(g::numeric) as c2, - count(*) as c3 - from agg_data_2k - where g < r.a - group by g/2) as s; -set jit_above_cost to default; -create table agg_group_3 as -select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3 - from agg_data_2k group by g/2; -create table agg_group_4 as -select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3 - from agg_data_2k group by g/2; --- Produce results with hash aggregation -set enable_hashagg = true; -set enable_sort = false; -set jit_above_cost = 0; -explain (costs off) -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; - QUERY PLAN --------------------------------- - HashAggregate - Group Key: (g % 10000) - -> Seq Scan on agg_data_20k -(3 rows) - -create table agg_hash_1 as -select g%10000 as c1, sum(g::numeric) as c2, count(*) as c3 - from agg_data_20k group by g%10000; -create table agg_hash_2 as -select * from - (values (100), (300), (500)) as r(a), - lateral ( - select (g/2)::numeric as c1, - array_agg(g::numeric) as c2, - count(*) as c3 - from agg_data_2k - where g < r.a - group by g/2) as s; -set jit_above_cost to default; -create table agg_hash_3 as -select (g/2)::numeric as c1, sum(7::int4) as c2, count(*) as c3 - from agg_data_2k group by g/2; -create table agg_hash_4 as -select (g/2)::numeric as c1, array_agg(g::numeric) as c2, count(*) as c3 - from agg_data_2k group by g/2; -set enable_sort = true; -set work_mem to default; --- Compare group aggregation results to hash aggregation results -(select * from agg_hash_1 except select * from agg_group_1) - union all -(select * from agg_group_1 except select * from agg_hash_1); - c1 | c2 | c3 -----+----+---- -(0 rows) - -(select * from agg_hash_2 except select * from agg_group_2) - union all -(select * from agg_group_2 except select * from agg_hash_2); - a | c1 | c2 | c3 ----+----+----+---- -(0 rows) - -(select * from agg_hash_3 except select * from agg_group_3) - union all -(select * from agg_group_3 except select * from agg_hash_3); - c1 | c2 | c3 -----+----+---- -(0 rows) - -(select * from agg_hash_4 except select * from agg_group_4) - union all -(select * from agg_group_4 except select * from agg_hash_4); - c1 | c2 | c3 -----+----+---- -(0 rows) - -drop table agg_group_1; -drop table agg_group_2; -drop table agg_group_3; -drop table agg_group_4; -drop table agg_hash_1; -drop table agg_hash_2; -drop table agg_hash_3; -drop table agg_hash_4; +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/random.out C:/cirrus/build/testrun/regress/regress/results/random.out --- C:/cirrus/src/test/regress/expected/random.out 2024-03-20 22:41:28.989690000 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/random.out 2024-03-20 22:44:01.589904500 +0000 @@ -1,178 +1,2 @@ --- --- RANDOM --- Test random() and allies --- --- Tests in this file may have a small probability of failure, --- since we are dealing with randomness. Try to keep the failure --- risk for any one test case under 1e-9. --- --- There should be no duplicates in 1000 random() values. --- (Assuming 52 random bits in the float8 results, we could --- take as many as 3000 values and still have less than 1e-9 chance --- of failure, per https://en.wikipedia.org/wiki/Birthday_problem) -SELECT r, count(*) -FROM (SELECT random() r FROM generate_series(1, 1000)) ss -GROUP BY r HAVING count(*) > 1; - r | count ----+------- -(0 rows) - --- The range should be [0, 1). We can expect that at least one out of 2000 --- random values is in the lowest or highest 1% of the range with failure --- probability less than about 1e-9. -SELECT count(*) FILTER (WHERE r < 0 OR r >= 1) AS out_of_range, - (count(*) FILTER (WHERE r < 0.01)) > 0 AS has_small, - (count(*) FILTER (WHERE r > 0.99)) > 0 AS has_large -FROM (SELECT random() r FROM generate_series(1, 2000)) ss; - out_of_range | has_small | has_large ---------------+-----------+----------- - 0 | t | t -(1 row) - --- Check for uniform distribution using the Kolmogorov-Smirnov test. -CREATE FUNCTION ks_test_uniform_random() -RETURNS boolean AS -$$ -DECLARE - n int := 1000; -- Number of samples - c float8 := 1.94947; -- Critical value for 99.9% confidence - ok boolean; -BEGIN - ok := ( - WITH samples AS ( - SELECT random() r FROM generate_series(1, n) ORDER BY 1 - ), indexed_samples AS ( - SELECT (row_number() OVER())-1.0 i, r FROM samples - ) - SELECT max(abs(i/n-r)) < c / sqrt(n) FROM indexed_samples - ); - RETURN ok; -END -$$ -LANGUAGE plpgsql; --- As written, ks_test_uniform_random() returns true about 99.9% --- of the time. To get down to a roughly 1e-9 test failure rate, --- just run it 3 times and accept if any one of them passes. -SELECT ks_test_uniform_random() OR - ks_test_uniform_random() OR - ks_test_uniform_random() AS uniform; - uniform ---------- - t -(1 row) - --- now test random_normal() --- As above, there should be no duplicates in 1000 random_normal() values. -SELECT r, count(*) -FROM (SELECT random_normal() r FROM generate_series(1, 1000)) ss -GROUP BY r HAVING count(*) > 1; - r | count ----+------- -(0 rows) - --- ... unless we force the range (standard deviation) to zero. --- This is a good place to check that the mean input does something, too. -SELECT r, count(*) -FROM (SELECT random_normal(10, 0) r FROM generate_series(1, 100)) ss -GROUP BY r; - r | count -----+------- - 10 | 100 -(1 row) - -SELECT r, count(*) -FROM (SELECT random_normal(-10, 0) r FROM generate_series(1, 100)) ss -GROUP BY r; - r | count ------+------- - -10 | 100 -(1 row) - --- Check standard normal distribution using the Kolmogorov-Smirnov test. -CREATE FUNCTION ks_test_normal_random() -RETURNS boolean AS -$$ -DECLARE - n int := 1000; -- Number of samples - c float8 := 1.94947; -- Critical value for 99.9% confidence - ok boolean; -BEGIN - ok := ( - WITH samples AS ( - SELECT random_normal() r FROM generate_series(1, n) ORDER BY 1 - ), indexed_samples AS ( - SELECT (row_number() OVER())-1.0 i, r FROM samples - ) - SELECT max(abs((1+erf(r/sqrt(2)))/2 - i/n)) < c / sqrt(n) - FROM indexed_samples - ); - RETURN ok; -END -$$ -LANGUAGE plpgsql; --- As above, ks_test_normal_random() returns true about 99.9% --- of the time, so try it 3 times and accept if any test passes. -SELECT ks_test_normal_random() OR - ks_test_normal_random() OR - ks_test_normal_random() AS standard_normal; - standard_normal ------------------ - t -(1 row) - --- setseed() should produce a reproducible series of random() values. -SELECT setseed(0.5); - setseed ---------- - -(1 row) - -SELECT random() FROM generate_series(1, 10); - random ---------------------- - 0.9851677175347999 - 0.825301858027981 - 0.12974610012450416 - 0.16356291958601088 - 0.6476186144084 - 0.8822771983038762 - 0.1404566845227775 - 0.15619865764623442 - 0.5145227426983392 - 0.7712969548127826 -(10 rows) - --- Likewise for random_normal(); however, since its implementation relies --- on libm functions that have different roundoff behaviors on different --- machines, we have to round off the results a bit to get consistent output. -SET extra_float_digits = -1; -SELECT random_normal() FROM generate_series(1, 10); - random_normal -------------------- - 0.20853464493838 - 0.26453024054096 - -0.60675246790043 - 0.82579942785265 - 1.7011161173536 - -0.22344546371619 - 0.249712419191 - -1.2494722990669 - 0.12562715204368 - 0.47539161454401 -(10 rows) - -SELECT random_normal(mean => 1, stddev => 0.1) r FROM generate_series(1, 10); - r ------------------- - 1.0060597281173 - 1.09685453015 - 1.0286920613201 - 0.90947567671234 - 0.98372476313426 - 0.93934454957762 - 1.1871350020636 - 0.96225768429293 - 0.91444120680041 - 0.96403105557543 -(10 rows) - +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/portals.out C:/cirrus/build/testrun/regress/regress/results/portals.out --- C:/cirrus/src/test/regress/expected/portals.out 2024-03-20 22:41:28.981860200 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/portals.out 2024-03-20 22:44:01.605530000 +0000 @@ -1,1563 +1,2 @@ --- --- Cursor regression tests --- -BEGIN; -DECLARE foo1 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo2 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo3 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo4 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo5 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo6 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo7 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo8 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo9 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo10 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo11 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo12 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo13 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo14 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo15 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo16 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo17 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo18 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo19 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo20 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo21 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -DECLARE foo22 SCROLL CURSOR FOR SELECT * FROM tenk2; -DECLARE foo23 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -FETCH 1 in foo1; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(1 row) - -FETCH 2 in foo2; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx -(2 rows) - -FETCH 3 in foo3; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx -(3 rows) - -FETCH 4 in foo4; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx -(4 rows) - -FETCH 5 in foo5; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx -(5 rows) - -FETCH 6 in foo6; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx -(6 rows) - -FETCH 7 in foo7; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx -(7 rows) - -FETCH 8 in foo8; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx -(8 rows) - -FETCH 9 in foo9; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx -(9 rows) - -FETCH 10 in foo10; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx -(10 rows) - -FETCH 11 in foo11; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx -(11 rows) - -FETCH 12 in foo12; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx -(12 rows) - -FETCH 13 in foo13; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx -(13 rows) - -FETCH 14 in foo14; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx -(14 rows) - -FETCH 15 in foo15; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx -(15 rows) - -FETCH 16 in foo16; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx -(16 rows) - -FETCH 17 in foo17; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx -(17 rows) - -FETCH 18 in foo18; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx -(18 rows) - -FETCH 19 in foo19; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx -(19 rows) - -FETCH 20 in foo20; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx - 6969 | 19 | 1 | 1 | 9 | 9 | 69 | 969 | 969 | 1969 | 6969 | 138 | 139 | BIAAAA | TAAAAA | VVVVxx -(20 rows) - -FETCH 21 in foo21; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx - 6969 | 19 | 1 | 1 | 9 | 9 | 69 | 969 | 969 | 1969 | 6969 | 138 | 139 | BIAAAA | TAAAAA | VVVVxx - 9460 | 20 | 0 | 0 | 0 | 0 | 60 | 460 | 1460 | 4460 | 9460 | 120 | 121 | WZAAAA | UAAAAA | AAAAxx -(21 rows) - -FETCH 22 in foo22; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx - 6969 | 19 | 1 | 1 | 9 | 9 | 69 | 969 | 969 | 1969 | 6969 | 138 | 139 | BIAAAA | TAAAAA | VVVVxx - 9460 | 20 | 0 | 0 | 0 | 0 | 60 | 460 | 1460 | 4460 | 9460 | 120 | 121 | WZAAAA | UAAAAA | AAAAxx - 59 | 21 | 1 | 3 | 9 | 19 | 59 | 59 | 59 | 59 | 59 | 118 | 119 | HCAAAA | VAAAAA | HHHHxx -(22 rows) - -FETCH 23 in foo23; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx - 6969 | 19 | 1 | 1 | 9 | 9 | 69 | 969 | 969 | 1969 | 6969 | 138 | 139 | BIAAAA | TAAAAA | VVVVxx - 9460 | 20 | 0 | 0 | 0 | 0 | 60 | 460 | 1460 | 4460 | 9460 | 120 | 121 | WZAAAA | UAAAAA | AAAAxx - 59 | 21 | 1 | 3 | 9 | 19 | 59 | 59 | 59 | 59 | 59 | 118 | 119 | HCAAAA | VAAAAA | HHHHxx - 8020 | 22 | 0 | 0 | 0 | 0 | 20 | 20 | 20 | 3020 | 8020 | 40 | 41 | MWAAAA | WAAAAA | OOOOxx -(23 rows) - -FETCH backward 1 in foo23; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 59 | 21 | 1 | 3 | 9 | 19 | 59 | 59 | 59 | 59 | 59 | 118 | 119 | HCAAAA | VAAAAA | HHHHxx -(1 row) - -FETCH backward 2 in foo22; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 9460 | 20 | 0 | 0 | 0 | 0 | 60 | 460 | 1460 | 4460 | 9460 | 120 | 121 | WZAAAA | UAAAAA | AAAAxx - 6969 | 19 | 1 | 1 | 9 | 9 | 69 | 969 | 969 | 1969 | 6969 | 138 | 139 | BIAAAA | TAAAAA | VVVVxx -(2 rows) - -FETCH backward 3 in foo21; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 6969 | 19 | 1 | 1 | 9 | 9 | 69 | 969 | 969 | 1969 | 6969 | 138 | 139 | BIAAAA | TAAAAA | VVVVxx - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx -(3 rows) - -FETCH backward 4 in foo20; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 6621 | 18 | 1 | 1 | 1 | 1 | 21 | 621 | 621 | 1621 | 6621 | 42 | 43 | RUAAAA | SAAAAA | OOOOxx - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx -(4 rows) - -FETCH backward 5 in foo19; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 5785 | 17 | 1 | 1 | 5 | 5 | 85 | 785 | 1785 | 785 | 5785 | 170 | 171 | NOAAAA | RAAAAA | HHHHxx - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx -(5 rows) - -FETCH backward 6 in foo18; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 5387 | 16 | 1 | 3 | 7 | 7 | 87 | 387 | 1387 | 387 | 5387 | 174 | 175 | FZAAAA | QAAAAA | AAAAxx - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx -(6 rows) - -FETCH backward 7 in foo17; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 5006 | 15 | 0 | 2 | 6 | 6 | 6 | 6 | 1006 | 6 | 5006 | 12 | 13 | OKAAAA | PAAAAA | VVVVxx - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx -(7 rows) - -FETCH backward 8 in foo16; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 5471 | 14 | 1 | 3 | 1 | 11 | 71 | 471 | 1471 | 471 | 5471 | 142 | 143 | LCAAAA | OAAAAA | OOOOxx - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx -(8 rows) - -FETCH backward 9 in foo15; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 6243 | 13 | 1 | 3 | 3 | 3 | 43 | 243 | 243 | 1243 | 6243 | 86 | 87 | DGAAAA | NAAAAA | HHHHxx - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx -(9 rows) - -FETCH backward 10 in foo14; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 5222 | 12 | 0 | 2 | 2 | 2 | 22 | 222 | 1222 | 222 | 5222 | 44 | 45 | WSAAAA | MAAAAA | AAAAxx - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx -(10 rows) - -FETCH backward 11 in foo13; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1504 | 11 | 0 | 0 | 4 | 4 | 4 | 504 | 1504 | 1504 | 1504 | 8 | 9 | WFAAAA | LAAAAA | VVVVxx - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx -(11 rows) - -FETCH backward 12 in foo12; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1314 | 10 | 0 | 2 | 4 | 14 | 14 | 314 | 1314 | 1314 | 1314 | 28 | 29 | OYAAAA | KAAAAA | OOOOxx - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(11 rows) - -FETCH backward 13 in foo11; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 3043 | 9 | 1 | 3 | 3 | 3 | 43 | 43 | 1043 | 3043 | 3043 | 86 | 87 | BNAAAA | JAAAAA | HHHHxx - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(10 rows) - -FETCH backward 14 in foo10; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 4321 | 8 | 1 | 1 | 1 | 1 | 21 | 321 | 321 | 4321 | 4321 | 42 | 43 | FKAAAA | IAAAAA | AAAAxx - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(9 rows) - -FETCH backward 15 in foo9; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 6701 | 7 | 1 | 1 | 1 | 1 | 1 | 701 | 701 | 1701 | 6701 | 2 | 3 | TXAAAA | HAAAAA | VVVVxx - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(8 rows) - -FETCH backward 16 in foo8; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 5057 | 6 | 1 | 1 | 7 | 17 | 57 | 57 | 1057 | 57 | 5057 | 114 | 115 | NMAAAA | GAAAAA | OOOOxx - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(7 rows) - -FETCH backward 17 in foo7; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8009 | 5 | 1 | 1 | 9 | 9 | 9 | 9 | 9 | 3009 | 8009 | 18 | 19 | BWAAAA | FAAAAA | HHHHxx - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(6 rows) - -FETCH backward 18 in foo6; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 7164 | 4 | 0 | 0 | 4 | 4 | 64 | 164 | 1164 | 2164 | 7164 | 128 | 129 | OPAAAA | EAAAAA | AAAAxx - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(5 rows) - -FETCH backward 19 in foo5; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(4 rows) - -FETCH backward 20 in foo4; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(3 rows) - -FETCH backward 21 in foo3; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(2 rows) - -FETCH backward 22 in foo2; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(1 row) - -FETCH backward 23 in foo1; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- -(0 rows) - -CLOSE foo1; -CLOSE foo2; -CLOSE foo3; -CLOSE foo4; -CLOSE foo5; -CLOSE foo6; -CLOSE foo7; -CLOSE foo8; -CLOSE foo9; -CLOSE foo10; -CLOSE foo11; -CLOSE foo12; --- leave some cursors open, to test that auto-close works. --- record this in the system view as well (don't query the time field there --- however) -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors ORDER BY 1; - name | statement | is_holdable | is_binary | is_scrollable --------+-----------------------------------------------------------------------+-------------+-----------+--------------- - foo13 | DECLARE foo13 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; | f | f | t - foo14 | DECLARE foo14 SCROLL CURSOR FOR SELECT * FROM tenk2; | f | f | t - foo15 | DECLARE foo15 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; | f | f | t - foo16 | DECLARE foo16 SCROLL CURSOR FOR SELECT * FROM tenk2; | f | f | t - foo17 | DECLARE foo17 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; | f | f | t - foo18 | DECLARE foo18 SCROLL CURSOR FOR SELECT * FROM tenk2; | f | f | t - foo19 | DECLARE foo19 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; | f | f | t - foo20 | DECLARE foo20 SCROLL CURSOR FOR SELECT * FROM tenk2; | f | f | t - foo21 | DECLARE foo21 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; | f | f | t - foo22 | DECLARE foo22 SCROLL CURSOR FOR SELECT * FROM tenk2; | f | f | t - foo23 | DECLARE foo23 SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; | f | f | t -(11 rows) - -END; -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; - name | statement | is_holdable | is_binary | is_scrollable -------+-----------+-------------+-----------+--------------- -(0 rows) - --- --- NO SCROLL disallows backward fetching --- -BEGIN; -DECLARE foo24 NO SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -FETCH 1 FROM foo24; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(1 row) - -FETCH BACKWARD 1 FROM foo24; -- should fail -ERROR: cursor can only scan forward -HINT: Declare it with SCROLL option to enable backward scan. -END; -BEGIN; -DECLARE foo24 NO SCROLL CURSOR FOR SELECT * FROM tenk1 ORDER BY unique2; -FETCH 1 FROM foo24; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(1 row) - -FETCH ABSOLUTE 2 FROM foo24; -- allowed - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx -(1 row) - -FETCH ABSOLUTE 1 FROM foo24; -- should fail -ERROR: cursor can only scan forward -HINT: Declare it with SCROLL option to enable backward scan. -END; --- --- Cursors outside transaction blocks --- -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; - name | statement | is_holdable | is_binary | is_scrollable -------+-----------+-------------+-----------+--------------- -(0 rows) - -BEGIN; -DECLARE foo25 SCROLL CURSOR WITH HOLD FOR SELECT * FROM tenk2; -FETCH FROM foo25; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(1 row) - -FETCH FROM foo25; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx -(1 row) - -COMMIT; -FETCH FROM foo25; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx -(1 row) - -FETCH BACKWARD FROM foo25; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx -(1 row) - -FETCH ABSOLUTE -1 FROM foo25; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 2968 | 9999 | 0 | 0 | 8 | 8 | 68 | 968 | 968 | 2968 | 2968 | 136 | 137 | EKAAAA | PUOAAA | VVVVxx -(1 row) - -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; - name | statement | is_holdable | is_binary | is_scrollable --------+----------------------------------------------------------------+-------------+-----------+--------------- - foo25 | DECLARE foo25 SCROLL CURSOR WITH HOLD FOR SELECT * FROM tenk2; | t | f | t -(1 row) - -CLOSE foo25; -BEGIN; -DECLARE foo25ns NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM tenk2; -FETCH FROM foo25ns; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 8800 | 0 | 0 | 0 | 0 | 0 | 0 | 800 | 800 | 3800 | 8800 | 0 | 1 | MAAAAA | AAAAAA | AAAAxx -(1 row) - -FETCH FROM foo25ns; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 1891 | 1 | 1 | 3 | 1 | 11 | 91 | 891 | 1891 | 1891 | 1891 | 182 | 183 | TUAAAA | BAAAAA | HHHHxx -(1 row) - -COMMIT; -FETCH FROM foo25ns; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 3420 | 2 | 0 | 0 | 0 | 0 | 20 | 420 | 1420 | 3420 | 3420 | 40 | 41 | OBAAAA | CAAAAA | OOOOxx -(1 row) - -FETCH ABSOLUTE 4 FROM foo25ns; - unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 ----------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- - 9850 | 3 | 0 | 2 | 0 | 10 | 50 | 850 | 1850 | 4850 | 9850 | 100 | 101 | WOAAAA | DAAAAA | VVVVxx -(1 row) - -FETCH ABSOLUTE 4 FROM foo25ns; -- fail -ERROR: cursor can only scan forward -HINT: Declare it with SCROLL option to enable backward scan. -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; - name | statement | is_holdable | is_binary | is_scrollable ----------+---------------------------------------------------------------------+-------------+-----------+--------------- - foo25ns | DECLARE foo25ns NO SCROLL CURSOR WITH HOLD FOR SELECT * FROM tenk2; | t | f | f -(1 row) - -CLOSE foo25ns; --- --- ROLLBACK should close holdable cursors --- -BEGIN; -DECLARE foo26 CURSOR WITH HOLD FOR SELECT * FROM tenk1 ORDER BY unique2; -ROLLBACK; --- should fail -FETCH FROM foo26; -ERROR: cursor "foo26" does not exist --- --- Parameterized DECLARE needs to insert param values into the cursor portal --- -BEGIN; -CREATE FUNCTION declares_cursor(text) - RETURNS void - AS 'DECLARE c CURSOR FOR SELECT stringu1 FROM tenk1 WHERE stringu1 LIKE $1;' - LANGUAGE SQL; -SELECT declares_cursor('AB%'); - declares_cursor ------------------ - -(1 row) - -FETCH ALL FROM c; - stringu1 ----------- - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA - ABAAAA -(15 rows) - -ROLLBACK; --- --- Test behavior of both volatile and stable functions inside a cursor; --- in particular we want to see what happens during commit of a holdable --- cursor --- -create temp table tt1(f1 int); -create function count_tt1_v() returns int8 as -'select count(*) from tt1' language sql volatile; -create function count_tt1_s() returns int8 as -'select count(*) from tt1' language sql stable; -begin; -insert into tt1 values(1); -declare c1 cursor for select count_tt1_v(), count_tt1_s(); -insert into tt1 values(2); -fetch all from c1; - count_tt1_v | count_tt1_s --------------+------------- - 2 | 1 -(1 row) - -rollback; -begin; -insert into tt1 values(1); -declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); -insert into tt1 values(2); -commit; -delete from tt1; -fetch all from c2; - count_tt1_v | count_tt1_s --------------+------------- - 2 | 1 -(1 row) - -drop function count_tt1_v(); -drop function count_tt1_s(); --- Create a cursor with the BINARY option and check the pg_cursors view -BEGIN; -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; - name | statement | is_holdable | is_binary | is_scrollable -------+----------------------------------------------------------------------+-------------+-----------+--------------- - c2 | declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); | t | f | f -(1 row) - -DECLARE bc BINARY CURSOR FOR SELECT * FROM tenk1; -SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors ORDER BY 1; - name | statement | is_holdable | is_binary | is_scrollable -------+----------------------------------------------------------------------+-------------+-----------+--------------- - bc | DECLARE bc BINARY CURSOR FOR SELECT * FROM tenk1; | f | t | t - c2 | declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); | t | f | f -(2 rows) - -ROLLBACK; --- We should not see the portal that is created internally to --- implement EXECUTE in pg_cursors -PREPARE cprep AS - SELECT name, statement, is_holdable, is_binary, is_scrollable FROM pg_cursors; -EXECUTE cprep; - name | statement | is_holdable | is_binary | is_scrollable -------+----------------------------------------------------------------------+-------------+-----------+--------------- - c2 | declare c2 cursor with hold for select count_tt1_v(), count_tt1_s(); | t | f | f -(1 row) - --- test CLOSE ALL; -SELECT name FROM pg_cursors ORDER BY 1; - name ------- - c2 -(1 row) - -CLOSE ALL; -SELECT name FROM pg_cursors ORDER BY 1; - name ------- -(0 rows) - -BEGIN; -DECLARE foo1 CURSOR WITH HOLD FOR SELECT 1; -DECLARE foo2 CURSOR WITHOUT HOLD FOR SELECT 1; -SELECT name FROM pg_cursors ORDER BY 1; - name ------- - foo1 - foo2 -(2 rows) - -CLOSE ALL; -SELECT name FROM pg_cursors ORDER BY 1; - name ------- -(0 rows) - -COMMIT; --- --- Tests for updatable cursors --- -CREATE TEMP TABLE uctest(f1 int, f2 text); -INSERT INTO uctest VALUES (1, 'one'), (2, 'two'), (3, 'three'); -SELECT * FROM uctest; - f1 | f2 -----+------- - 1 | one - 2 | two - 3 | three -(3 rows) - --- Check DELETE WHERE CURRENT -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest; -FETCH 2 FROM c1; - f1 | f2 -----+----- - 1 | one - 2 | two -(2 rows) - -DELETE FROM uctest WHERE CURRENT OF c1; --- should show deletion -SELECT * FROM uctest; - f1 | f2 -----+------- - 1 | one - 3 | three -(2 rows) - --- cursor did not move -FETCH ALL FROM c1; - f1 | f2 -----+------- - 3 | three -(1 row) - --- cursor is insensitive -MOVE BACKWARD ALL IN c1; -FETCH ALL FROM c1; - f1 | f2 -----+------- - 1 | one - 2 | two - 3 | three -(3 rows) - -COMMIT; --- should still see deletion -SELECT * FROM uctest; - f1 | f2 -----+------- - 1 | one - 3 | three -(2 rows) - --- Check UPDATE WHERE CURRENT; this time use FOR UPDATE -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE; -FETCH c1; - f1 | f2 -----+----- - 1 | one -(1 row) - -UPDATE uctest SET f1 = 8 WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+------- - 3 | three - 8 | one -(2 rows) - -COMMIT; -SELECT * FROM uctest; - f1 | f2 -----+------- - 3 | three - 8 | one -(2 rows) - --- Check repeated-update and update-then-delete cases -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest; -FETCH c1; - f1 | f2 -----+------- - 3 | three -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+------- - 8 | one - 13 | three -(2 rows) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+------- - 8 | one - 23 | three -(2 rows) - --- insensitive cursor should not show effects of updates or deletes -FETCH RELATIVE 0 FROM c1; - f1 | f2 -----+------- - 3 | three -(1 row) - -DELETE FROM uctest WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+----- - 8 | one -(1 row) - -DELETE FROM uctest WHERE CURRENT OF c1; -- no-op -SELECT * FROM uctest; - f1 | f2 -----+----- - 8 | one -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op -SELECT * FROM uctest; - f1 | f2 -----+----- - 8 | one -(1 row) - -FETCH RELATIVE 0 FROM c1; - f1 | f2 -----+------- - 3 | three -(1 row) - -ROLLBACK; -SELECT * FROM uctest; - f1 | f2 -----+------- - 3 | three - 8 | one -(2 rows) - -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE; -FETCH c1; - f1 | f2 -----+------- - 3 | three -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+------- - 8 | one - 13 | three -(2 rows) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+------- - 8 | one - 23 | three -(2 rows) - -DELETE FROM uctest WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 -----+----- - 8 | one -(1 row) - -DELETE FROM uctest WHERE CURRENT OF c1; -- no-op -SELECT * FROM uctest; - f1 | f2 -----+----- - 8 | one -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- no-op -SELECT * FROM uctest; - f1 | f2 -----+----- - 8 | one -(1 row) - ---- FOR UPDATE cursors can't currently scroll back, so this is an error: -FETCH RELATIVE 0 FROM c1; -ERROR: cursor can only scan forward -HINT: Declare it with SCROLL option to enable backward scan. -ROLLBACK; -SELECT * FROM uctest; - f1 | f2 -----+------- - 3 | three - 8 | one -(2 rows) - --- Check insensitive cursor with INSERT --- (The above tests don't test the SQL notion of an insensitive cursor --- correctly, because per SQL standard, changes from WHERE CURRENT OF --- commands should be visible in the cursor. So here we make the --- changes with a command that is independent of the cursor.) -BEGIN; -DECLARE c1 INSENSITIVE CURSOR FOR SELECT * FROM uctest; -INSERT INTO uctest VALUES (10, 'ten'); -FETCH NEXT FROM c1; - f1 | f2 -----+------- - 3 | three -(1 row) - -FETCH NEXT FROM c1; - f1 | f2 -----+----- - 8 | one -(1 row) - -FETCH NEXT FROM c1; -- insert not visible - f1 | f2 -----+---- -(0 rows) - -COMMIT; -SELECT * FROM uctest; - f1 | f2 -----+------- - 3 | three - 8 | one - 10 | ten -(3 rows) - -DELETE FROM uctest WHERE f1 = 10; -- restore test table state --- Check inheritance cases -CREATE TEMP TABLE ucchild () inherits (uctest); -INSERT INTO ucchild values(100, 'hundred'); -SELECT * FROM uctest; - f1 | f2 ------+--------- - 3 | three - 8 | one - 100 | hundred -(3 rows) - -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest FOR UPDATE; -FETCH 1 FROM c1; - f1 | f2 -----+------- - 3 | three -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -FETCH 1 FROM c1; - f1 | f2 -----+----- - 8 | one -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -FETCH 1 FROM c1; - f1 | f2 ------+--------- - 100 | hundred -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -FETCH 1 FROM c1; - f1 | f2 -----+---- -(0 rows) - -COMMIT; -SELECT * FROM uctest; - f1 | f2 ------+--------- - 13 | three - 18 | one - 110 | hundred -(3 rows) - --- Can update from a self-join, but only if FOR UPDATE says which to use -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest a, uctest b WHERE a.f1 = b.f1 + 5; -FETCH 1 FROM c1; - f1 | f2 | f1 | f2 -----+-----+----+------- - 18 | one | 13 | three -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- fail -ERROR: cursor "c1" is not a simply updatable scan of table "uctest" -ROLLBACK; -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest a, uctest b WHERE a.f1 = b.f1 + 5 FOR UPDATE; -FETCH 1 FROM c1; - f1 | f2 | f1 | f2 -----+-----+----+------- - 18 | one | 13 | three -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -- fail -ERROR: cursor "c1" has multiple FOR UPDATE/SHARE references to table "uctest" -ROLLBACK; -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest a, uctest b WHERE a.f1 = b.f1 + 5 FOR SHARE OF a; -FETCH 1 FROM c1; - f1 | f2 | f1 | f2 -----+-----+----+------- - 18 | one | 13 | three -(1 row) - -UPDATE uctest SET f1 = f1 + 10 WHERE CURRENT OF c1; -SELECT * FROM uctest; - f1 | f2 ------+--------- - 13 | three - 28 | one - 110 | hundred -(3 rows) - -ROLLBACK; --- Check various error cases -DELETE FROM uctest WHERE CURRENT OF c1; -- fail, no such cursor -ERROR: cursor "c1" does not exist -DECLARE cx CURSOR WITH HOLD FOR SELECT * FROM uctest; -DELETE FROM uctest WHERE CURRENT OF cx; -- fail, can't use held cursor -ERROR: cursor "cx" is held from a previous transaction -BEGIN; -DECLARE c CURSOR FOR SELECT * FROM tenk2; -DELETE FROM uctest WHERE CURRENT OF c; -- fail, cursor on wrong table -ERROR: cursor "c" is not a simply updatable scan of table "uctest" -ROLLBACK; -BEGIN; -DECLARE c CURSOR FOR SELECT * FROM tenk2 FOR SHARE; -DELETE FROM uctest WHERE CURRENT OF c; -- fail, cursor on wrong table -ERROR: cursor "c" does not have a FOR UPDATE/SHARE reference to table "uctest" -ROLLBACK; -BEGIN; -DECLARE c CURSOR FOR SELECT * FROM tenk1 JOIN tenk2 USING (unique1); -DELETE FROM tenk1 WHERE CURRENT OF c; -- fail, cursor is on a join -ERROR: cursor "c" is not a simply updatable scan of table "tenk1" -ROLLBACK; -BEGIN; -DECLARE c CURSOR FOR SELECT f1,count(*) FROM uctest GROUP BY f1; -DELETE FROM uctest WHERE CURRENT OF c; -- fail, cursor is on aggregation -ERROR: cursor "c" is not a simply updatable scan of table "uctest" -ROLLBACK; -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM uctest; -DELETE FROM uctest WHERE CURRENT OF c1; -- fail, no current row -ERROR: cursor "c1" is not positioned on a row -ROLLBACK; -BEGIN; -DECLARE c1 CURSOR FOR SELECT MIN(f1) FROM uctest FOR UPDATE; -ERROR: FOR UPDATE is not allowed with aggregate functions -ROLLBACK; --- WHERE CURRENT OF may someday work with views, but today is not that day. --- For now, just make sure it errors out cleanly. -CREATE TEMP VIEW ucview AS SELECT * FROM uctest; -CREATE RULE ucrule AS ON DELETE TO ucview DO INSTEAD - DELETE FROM uctest WHERE f1 = OLD.f1; -BEGIN; -DECLARE c1 CURSOR FOR SELECT * FROM ucview; -FETCH FROM c1; - f1 | f2 -----+------- - 13 | three -(1 row) - -DELETE FROM ucview WHERE CURRENT OF c1; -- fail, views not supported -ERROR: WHERE CURRENT OF on a view is not implemented -ROLLBACK; --- Check WHERE CURRENT OF with an index-only scan -BEGIN; -EXPLAIN (costs off) -DECLARE c1 CURSOR FOR SELECT stringu1 FROM onek WHERE stringu1 = 'DZAAAA'; - QUERY PLAN ---------------------------------------------- - Index Only Scan using onek_stringu1 on onek - Index Cond: (stringu1 = 'DZAAAA'::name) -(2 rows) - -DECLARE c1 CURSOR FOR SELECT stringu1 FROM onek WHERE stringu1 = 'DZAAAA'; -FETCH FROM c1; - stringu1 ----------- - DZAAAA -(1 row) - -DELETE FROM onek WHERE CURRENT OF c1; -SELECT stringu1 FROM onek WHERE stringu1 = 'DZAAAA'; - stringu1 ----------- -(0 rows) - -ROLLBACK; --- Check behavior with rewinding to a previous child scan node, --- as per bug #15395 -BEGIN; -CREATE TABLE current_check (currentid int, payload text); -CREATE TABLE current_check_1 () INHERITS (current_check); -CREATE TABLE current_check_2 () INHERITS (current_check); -INSERT INTO current_check_1 SELECT i, 'p' || i FROM generate_series(1,9) i; -INSERT INTO current_check_2 SELECT i, 'P' || i FROM generate_series(10,19) i; -DECLARE c1 SCROLL CURSOR FOR SELECT * FROM current_check; --- This tests the fetch-backwards code path -FETCH ABSOLUTE 12 FROM c1; - currentid | payload ------------+--------- - 12 | P12 -(1 row) - -FETCH ABSOLUTE 8 FROM c1; - currentid | payload ------------+--------- - 8 | p8 -(1 row) - -DELETE FROM current_check WHERE CURRENT OF c1 RETURNING *; - currentid | payload ------------+--------- - 8 | p8 -(1 row) - --- This tests the ExecutorRewind code path -FETCH ABSOLUTE 13 FROM c1; - currentid | payload ------------+--------- - 13 | P13 -(1 row) - -FETCH ABSOLUTE 1 FROM c1; - currentid | payload ------------+--------- - 1 | p1 -(1 row) - -DELETE FROM current_check WHERE CURRENT OF c1 RETURNING *; - currentid | payload ------------+--------- - 1 | p1 -(1 row) - -SELECT * FROM current_check; - currentid | payload ------------+--------- - 2 | p2 - 3 | p3 - 4 | p4 - 5 | p5 - 6 | p6 - 7 | p7 - 9 | p9 - 10 | P10 - 11 | P11 - 12 | P12 - 13 | P13 - 14 | P14 - 15 | P15 - 16 | P16 - 17 | P17 - 18 | P18 - 19 | P19 -(17 rows) - -ROLLBACK; --- Make sure snapshot management works okay, per bug report in --- 235395b90909301035v7228ce63q392931f15aa74b31@mail.gmail.com -BEGIN; -SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; -CREATE TABLE cursor (a int); -INSERT INTO cursor VALUES (1); -DECLARE c1 NO SCROLL CURSOR FOR SELECT * FROM cursor FOR UPDATE; -UPDATE cursor SET a = 2; -FETCH ALL FROM c1; - a ---- -(0 rows) - -COMMIT; -DROP TABLE cursor; --- Check rewinding a cursor containing a stable function in LIMIT, --- per bug report in 8336843.9833.1399385291498.JavaMail.root@quick -begin; -create function nochange(int) returns int - as 'select $1 limit 1' language sql stable; -declare c cursor for select * from int8_tbl limit nochange(3); -fetch all from c; - q1 | q2 -------------------+------------------ - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 -(3 rows) - -move backward all in c; -fetch all from c; - q1 | q2 -------------------+------------------ - 123 | 456 - 123 | 4567890123456789 - 4567890123456789 | 123 -(3 rows) - -rollback; --- Check handling of non-backwards-scan-capable plans with scroll cursors -begin; -explain (costs off) declare c1 cursor for select (select 42) as x; - QUERY PLAN ----------------- - Result - InitPlan 1 - -> Result -(3 rows) - -explain (costs off) declare c1 scroll cursor for select (select 42) as x; - QUERY PLAN ----------------- - Materialize - InitPlan 1 - -> Result - -> Result -(4 rows) - -declare c1 scroll cursor for select (select 42) as x; -fetch all in c1; - x ----- - 42 -(1 row) - -fetch backward all in c1; - x ----- - 42 -(1 row) - -rollback; -begin; -explain (costs off) declare c2 cursor for select generate_series(1,3) as g; - QUERY PLAN --------------- - ProjectSet - -> Result -(2 rows) - -explain (costs off) declare c2 scroll cursor for select generate_series(1,3) as g; - QUERY PLAN --------------------- - Materialize - -> ProjectSet - -> Result -(3 rows) - -declare c2 scroll cursor for select generate_series(1,3) as g; -fetch all in c2; - g ---- - 1 - 2 - 3 -(3 rows) - -fetch backward all in c2; - g ---- - 3 - 2 - 1 -(3 rows) - -rollback; --- Check fetching of toasted datums via cursors. -begin; --- Other compression algorithms may cause the compressed data to be stored --- inline. Use pglz to ensure consistent results. -set default_toast_compression = 'pglz'; -create table toasted_data (f1 int[]); -insert into toasted_data - select array_agg(i) from generate_series(12345678, 12345678 + 1000) i; -declare local_portal cursor for select * from toasted_data; -fetch all in local_portal; - f1 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - {12345678,12345679,12345680,12345681,12345682,12345683,12345684,12345685,12345686,12345687,12345688,12345689,12345690,12345691,12345692,12345693,12345694,12345695,12345696,12345697,12345698,12345699,12345700,12345701,12345702,12345703,12345704,12345705,12345706,12345707,12345708,12345709,12345710,12345711,12345712,12345713,12345714,12345715,12345716,12345717,12345718,12345719,12345720,12345721,12345722,12345723,12345724,12345725,12345726,12345727,12345728,12345729,12345730,12345731,12345732,12345733,12345734,12345735,12345736,12345737,12345738,12345739,12345740,12345741,12345742,12345743,12345744,12345745,12345746,12345747,12345748,12345749,12345750,12345751,12345752,12345753,12345754,12345755,12345756,12345757,12345758,12345759,12345760,12345761,12345762,12345763,12345764,12345765,12345766,12345767,12345768,12345769,12345770,12345771,12345772,12345773,12345774,12345775,12345776,12345777,12345778,12345779,12345780,12345781,12345782,12345783,12345784,12345785,12345786,12345787,12345788,12345789,12345790,12345791,12345792,12345793,12345794,12345795,12345796,12345797,12345798,12345799,12345800,12345801,12345802,12345803,12345804,12345805,12345806,12345807,12345808,12345809,12345810,12345811,12345812,12345813,12345814,12345815,12345816,12345817,12345818,12345819,12345820,12345821,12345822,12345823,12345824,12345825,12345826,12345827,12345828,12345829,12345830,12345831,12345832,12345833,12345834,12345835,12345836,12345837,12345838,12345839,12345840,12345841,12345842,12345843,12345844,12345845,12345846,12345847,12345848,12345849,12345850,12345851,12345852,12345853,12345854,12345855,12345856,12345857,12345858,12345859,12345860,12345861,12345862,12345863,12345864,12345865,12345866,12345867,12345868,12345869,12345870,12345871,12345872,12345873,12345874,12345875,12345876,12345877,12345878,12345879,12345880,12345881,12345882,12345883,12345884,12345885,12345886,12345887,12345888,12345889,12345890,12345891,12345892,12345893,12345894,12345895,12345896,12345897,12345898,12345899,12345900,12345901,12345902,12345903,12345904,12345905,12345906,12345907,12345908,12345909,12345910,12345911,12345912,12345913,12345914,12345915,12345916,12345917,12345918,12345919,12345920,12345921,12345922,12345923,12345924,12345925,12345926,12345927,12345928,12345929,12345930,12345931,12345932,12345933,12345934,12345935,12345936,12345937,12345938,12345939,12345940,12345941,12345942,12345943,12345944,12345945,12345946,12345947,12345948,12345949,12345950,12345951,12345952,12345953,12345954,12345955,12345956,12345957,12345958,12345959,12345960,12345961,12345962,12345963,12345964,12345965,12345966,12345967,12345968,12345969,12345970,12345971,12345972,12345973,12345974,12345975,12345976,12345977,12345978,12345979,12345980,12345981,12345982,12345983,12345984,12345985,12345986,12345987,12345988,12345989,12345990,12345991,12345992,12345993,12345994,12345995,12345996,12345997,12345998,12345999,12346000,12346001,12346002,12346003,12346004,12346005,12346006,12346007,12346008,12346009,12346010,12346011,12346012,12346013,12346014,12346015,12346016,12346017,12346018,12346019,12346020,12346021,12346022,12346023,12346024,12346025,12346026,12346027,12346028,12346029,12346030,12346031,12346032,12346033,12346034,12346035,12346036,12346037,12346038,12346039,12346040,12346041,12346042,12346043,12346044,12346045,12346046,12346047,12346048,12346049,12346050,12346051,12346052,12346053,12346054,12346055,12346056,12346057,12346058,12346059,12346060,12346061,12346062,12346063,12346064,12346065,12346066,12346067,12346068,12346069,12346070,12346071,12346072,12346073,12346074,12346075,12346076,12346077,12346078,12346079,12346080,12346081,12346082,12346083,12346084,12346085,12346086,12346087,12346088,12346089,12346090,12346091,12346092,12346093,12346094,12346095,12346096,12346097,12346098,12346099,12346100,12346101,12346102,12346103,12346104,12346105,12346106,12346107,12346108,12346109,12346110,12346111,12346112,12346113,12346114,12346115,12346116,12346117,12346118,12346119,12346120,12346121,12346122,12346123,12346124,12346125,12346126,12346127,12346128,12346129,12346130,12346131,12346132,12346133,12346134,12346135,12346136,12346137,12346138,12346139,12346140,12346141,12346142,12346143,12346144,12346145,12346146,12346147,12346148,12346149,12346150,12346151,12346152,12346153,12346154,12346155,12346156,12346157,12346158,12346159,12346160,12346161,12346162,12346163,12346164,12346165,12346166,12346167,12346168,12346169,12346170,12346171,12346172,12346173,12346174,12346175,12346176,12346177,12346178,12346179,12346180,12346181,12346182,12346183,12346184,12346185,12346186,12346187,12346188,12346189,12346190,12346191,12346192,12346193,12346194,12346195,12346196,12346197,12346198,12346199,12346200,12346201,12346202,12346203,12346204,12346205,12346206,12346207,12346208,12346209,12346210,12346211,12346212,12346213,12346214,12346215,12346216,12346217,12346218,12346219,12346220,12346221,12346222,12346223,12346224,12346225,12346226,12346227,12346228,12346229,12346230,12346231,12346232,12346233,12346234,12346235,12346236,12346237,12346238,12346239,12346240,12346241,12346242,12346243,12346244,12346245,12346246,12346247,12346248,12346249,12346250,12346251,12346252,12346253,12346254,12346255,12346256,12346257,12346258,12346259,12346260,12346261,12346262,12346263,12346264,12346265,12346266,12346267,12346268,12346269,12346270,12346271,12346272,12346273,12346274,12346275,12346276,12346277,12346278,12346279,12346280,12346281,12346282,12346283,12346284,12346285,12346286,12346287,12346288,12346289,12346290,12346291,12346292,12346293,12346294,12346295,12346296,12346297,12346298,12346299,12346300,12346301,12346302,12346303,12346304,12346305,12346306,12346307,12346308,12346309,12346310,12346311,12346312,12346313,12346314,12346315,12346316,12346317,12346318,12346319,12346320,12346321,12346322,12346323,12346324,12346325,12346326,12346327,12346328,12346329,12346330,12346331,12346332,12346333,12346334,12346335,12346336,12346337,12346338,12346339,12346340,12346341,12346342,12346343,12346344,12346345,12346346,12346347,12346348,12346349,12346350,12346351,12346352,12346353,12346354,12346355,12346356,12346357,12346358,12346359,12346360,12346361,12346362,12346363,12346364,12346365,12346366,12346367,12346368,12346369,12346370,12346371,12346372,12346373,12346374,12346375,12346376,12346377,12346378,12346379,12346380,12346381,12346382,12346383,12346384,12346385,12346386,12346387,12346388,12346389,12346390,12346391,12346392,12346393,12346394,12346395,12346396,12346397,12346398,12346399,12346400,12346401,12346402,12346403,12346404,12346405,12346406,12346407,12346408,12346409,12346410,12346411,12346412,12346413,12346414,12346415,12346416,12346417,12346418,12346419,12346420,12346421,12346422,12346423,12346424,12346425,12346426,12346427,12346428,12346429,12346430,12346431,12346432,12346433,12346434,12346435,12346436,12346437,12346438,12346439,12346440,12346441,12346442,12346443,12346444,12346445,12346446,12346447,12346448,12346449,12346450,12346451,12346452,12346453,12346454,12346455,12346456,12346457,12346458,12346459,12346460,12346461,12346462,12346463,12346464,12346465,12346466,12346467,12346468,12346469,12346470,12346471,12346472,12346473,12346474,12346475,12346476,12346477,12346478,12346479,12346480,12346481,12346482,12346483,12346484,12346485,12346486,12346487,12346488,12346489,12346490,12346491,12346492,12346493,12346494,12346495,12346496,12346497,12346498,12346499,12346500,12346501,12346502,12346503,12346504,12346505,12346506,12346507,12346508,12346509,12346510,12346511,12346512,12346513,12346514,12346515,12346516,12346517,12346518,12346519,12346520,12346521,12346522,12346523,12346524,12346525,12346526,12346527,12346528,12346529,12346530,12346531,12346532,12346533,12346534,12346535,12346536,12346537,12346538,12346539,12346540,12346541,12346542,12346543,12346544,12346545,12346546,12346547,12346548,12346549,12346550,12346551,12346552,12346553,12346554,12346555,12346556,12346557,12346558,12346559,12346560,12346561,12346562,12346563,12346564,12346565,12346566,12346567,12346568,12346569,12346570,12346571,12346572,12346573,12346574,12346575,12346576,12346577,12346578,12346579,12346580,12346581,12346582,12346583,12346584,12346585,12346586,12346587,12346588,12346589,12346590,12346591,12346592,12346593,12346594,12346595,12346596,12346597,12346598,12346599,12346600,12346601,12346602,12346603,12346604,12346605,12346606,12346607,12346608,12346609,12346610,12346611,12346612,12346613,12346614,12346615,12346616,12346617,12346618,12346619,12346620,12346621,12346622,12346623,12346624,12346625,12346626,12346627,12346628,12346629,12346630,12346631,12346632,12346633,12346634,12346635,12346636,12346637,12346638,12346639,12346640,12346641,12346642,12346643,12346644,12346645,12346646,12346647,12346648,12346649,12346650,12346651,12346652,12346653,12346654,12346655,12346656,12346657,12346658,12346659,12346660,12346661,12346662,12346663,12346664,12346665,12346666,12346667,12346668,12346669,12346670,12346671,12346672,12346673,12346674,12346675,12346676,12346677,12346678} -(1 row) - -declare held_portal cursor with hold for select * from toasted_data; -commit; -drop table toasted_data; -fetch all in held_portal; - f1 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - {12345678,12345679,12345680,12345681,12345682,12345683,12345684,12345685,12345686,12345687,12345688,12345689,12345690,12345691,12345692,12345693,12345694,12345695,12345696,12345697,12345698,12345699,12345700,12345701,12345702,12345703,12345704,12345705,12345706,12345707,12345708,12345709,12345710,12345711,12345712,12345713,12345714,12345715,12345716,12345717,12345718,12345719,12345720,12345721,12345722,12345723,12345724,12345725,12345726,12345727,12345728,12345729,12345730,12345731,12345732,12345733,12345734,12345735,12345736,12345737,12345738,12345739,12345740,12345741,12345742,12345743,12345744,12345745,12345746,12345747,12345748,12345749,12345750,12345751,12345752,12345753,12345754,12345755,12345756,12345757,12345758,12345759,12345760,12345761,12345762,12345763,12345764,12345765,12345766,12345767,12345768,12345769,12345770,12345771,12345772,12345773,12345774,12345775,12345776,12345777,12345778,12345779,12345780,12345781,12345782,12345783,12345784,12345785,12345786,12345787,12345788,12345789,12345790,12345791,12345792,12345793,12345794,12345795,12345796,12345797,12345798,12345799,12345800,12345801,12345802,12345803,12345804,12345805,12345806,12345807,12345808,12345809,12345810,12345811,12345812,12345813,12345814,12345815,12345816,12345817,12345818,12345819,12345820,12345821,12345822,12345823,12345824,12345825,12345826,12345827,12345828,12345829,12345830,12345831,12345832,12345833,12345834,12345835,12345836,12345837,12345838,12345839,12345840,12345841,12345842,12345843,12345844,12345845,12345846,12345847,12345848,12345849,12345850,12345851,12345852,12345853,12345854,12345855,12345856,12345857,12345858,12345859,12345860,12345861,12345862,12345863,12345864,12345865,12345866,12345867,12345868,12345869,12345870,12345871,12345872,12345873,12345874,12345875,12345876,12345877,12345878,12345879,12345880,12345881,12345882,12345883,12345884,12345885,12345886,12345887,12345888,12345889,12345890,12345891,12345892,12345893,12345894,12345895,12345896,12345897,12345898,12345899,12345900,12345901,12345902,12345903,12345904,12345905,12345906,12345907,12345908,12345909,12345910,12345911,12345912,12345913,12345914,12345915,12345916,12345917,12345918,12345919,12345920,12345921,12345922,12345923,12345924,12345925,12345926,12345927,12345928,12345929,12345930,12345931,12345932,12345933,12345934,12345935,12345936,12345937,12345938,12345939,12345940,12345941,12345942,12345943,12345944,12345945,12345946,12345947,12345948,12345949,12345950,12345951,12345952,12345953,12345954,12345955,12345956,12345957,12345958,12345959,12345960,12345961,12345962,12345963,12345964,12345965,12345966,12345967,12345968,12345969,12345970,12345971,12345972,12345973,12345974,12345975,12345976,12345977,12345978,12345979,12345980,12345981,12345982,12345983,12345984,12345985,12345986,12345987,12345988,12345989,12345990,12345991,12345992,12345993,12345994,12345995,12345996,12345997,12345998,12345999,12346000,12346001,12346002,12346003,12346004,12346005,12346006,12346007,12346008,12346009,12346010,12346011,12346012,12346013,12346014,12346015,12346016,12346017,12346018,12346019,12346020,12346021,12346022,12346023,12346024,12346025,12346026,12346027,12346028,12346029,12346030,12346031,12346032,12346033,12346034,12346035,12346036,12346037,12346038,12346039,12346040,12346041,12346042,12346043,12346044,12346045,12346046,12346047,12346048,12346049,12346050,12346051,12346052,12346053,12346054,12346055,12346056,12346057,12346058,12346059,12346060,12346061,12346062,12346063,12346064,12346065,12346066,12346067,12346068,12346069,12346070,12346071,12346072,12346073,12346074,12346075,12346076,12346077,12346078,12346079,12346080,12346081,12346082,12346083,12346084,12346085,12346086,12346087,12346088,12346089,12346090,12346091,12346092,12346093,12346094,12346095,12346096,12346097,12346098,12346099,12346100,12346101,12346102,12346103,12346104,12346105,12346106,12346107,12346108,12346109,12346110,12346111,12346112,12346113,12346114,12346115,12346116,12346117,12346118,12346119,12346120,12346121,12346122,12346123,12346124,12346125,12346126,12346127,12346128,12346129,12346130,12346131,12346132,12346133,12346134,12346135,12346136,12346137,12346138,12346139,12346140,12346141,12346142,12346143,12346144,12346145,12346146,12346147,12346148,12346149,12346150,12346151,12346152,12346153,12346154,12346155,12346156,12346157,12346158,12346159,12346160,12346161,12346162,12346163,12346164,12346165,12346166,12346167,12346168,12346169,12346170,12346171,12346172,12346173,12346174,12346175,12346176,12346177,12346178,12346179,12346180,12346181,12346182,12346183,12346184,12346185,12346186,12346187,12346188,12346189,12346190,12346191,12346192,12346193,12346194,12346195,12346196,12346197,12346198,12346199,12346200,12346201,12346202,12346203,12346204,12346205,12346206,12346207,12346208,12346209,12346210,12346211,12346212,12346213,12346214,12346215,12346216,12346217,12346218,12346219,12346220,12346221,12346222,12346223,12346224,12346225,12346226,12346227,12346228,12346229,12346230,12346231,12346232,12346233,12346234,12346235,12346236,12346237,12346238,12346239,12346240,12346241,12346242,12346243,12346244,12346245,12346246,12346247,12346248,12346249,12346250,12346251,12346252,12346253,12346254,12346255,12346256,12346257,12346258,12346259,12346260,12346261,12346262,12346263,12346264,12346265,12346266,12346267,12346268,12346269,12346270,12346271,12346272,12346273,12346274,12346275,12346276,12346277,12346278,12346279,12346280,12346281,12346282,12346283,12346284,12346285,12346286,12346287,12346288,12346289,12346290,12346291,12346292,12346293,12346294,12346295,12346296,12346297,12346298,12346299,12346300,12346301,12346302,12346303,12346304,12346305,12346306,12346307,12346308,12346309,12346310,12346311,12346312,12346313,12346314,12346315,12346316,12346317,12346318,12346319,12346320,12346321,12346322,12346323,12346324,12346325,12346326,12346327,12346328,12346329,12346330,12346331,12346332,12346333,12346334,12346335,12346336,12346337,12346338,12346339,12346340,12346341,12346342,12346343,12346344,12346345,12346346,12346347,12346348,12346349,12346350,12346351,12346352,12346353,12346354,12346355,12346356,12346357,12346358,12346359,12346360,12346361,12346362,12346363,12346364,12346365,12346366,12346367,12346368,12346369,12346370,12346371,12346372,12346373,12346374,12346375,12346376,12346377,12346378,12346379,12346380,12346381,12346382,12346383,12346384,12346385,12346386,12346387,12346388,12346389,12346390,12346391,12346392,12346393,12346394,12346395,12346396,12346397,12346398,12346399,12346400,12346401,12346402,12346403,12346404,12346405,12346406,12346407,12346408,12346409,12346410,12346411,12346412,12346413,12346414,12346415,12346416,12346417,12346418,12346419,12346420,12346421,12346422,12346423,12346424,12346425,12346426,12346427,12346428,12346429,12346430,12346431,12346432,12346433,12346434,12346435,12346436,12346437,12346438,12346439,12346440,12346441,12346442,12346443,12346444,12346445,12346446,12346447,12346448,12346449,12346450,12346451,12346452,12346453,12346454,12346455,12346456,12346457,12346458,12346459,12346460,12346461,12346462,12346463,12346464,12346465,12346466,12346467,12346468,12346469,12346470,12346471,12346472,12346473,12346474,12346475,12346476,12346477,12346478,12346479,12346480,12346481,12346482,12346483,12346484,12346485,12346486,12346487,12346488,12346489,12346490,12346491,12346492,12346493,12346494,12346495,12346496,12346497,12346498,12346499,12346500,12346501,12346502,12346503,12346504,12346505,12346506,12346507,12346508,12346509,12346510,12346511,12346512,12346513,12346514,12346515,12346516,12346517,12346518,12346519,12346520,12346521,12346522,12346523,12346524,12346525,12346526,12346527,12346528,12346529,12346530,12346531,12346532,12346533,12346534,12346535,12346536,12346537,12346538,12346539,12346540,12346541,12346542,12346543,12346544,12346545,12346546,12346547,12346548,12346549,12346550,12346551,12346552,12346553,12346554,12346555,12346556,12346557,12346558,12346559,12346560,12346561,12346562,12346563,12346564,12346565,12346566,12346567,12346568,12346569,12346570,12346571,12346572,12346573,12346574,12346575,12346576,12346577,12346578,12346579,12346580,12346581,12346582,12346583,12346584,12346585,12346586,12346587,12346588,12346589,12346590,12346591,12346592,12346593,12346594,12346595,12346596,12346597,12346598,12346599,12346600,12346601,12346602,12346603,12346604,12346605,12346606,12346607,12346608,12346609,12346610,12346611,12346612,12346613,12346614,12346615,12346616,12346617,12346618,12346619,12346620,12346621,12346622,12346623,12346624,12346625,12346626,12346627,12346628,12346629,12346630,12346631,12346632,12346633,12346634,12346635,12346636,12346637,12346638,12346639,12346640,12346641,12346642,12346643,12346644,12346645,12346646,12346647,12346648,12346649,12346650,12346651,12346652,12346653,12346654,12346655,12346656,12346657,12346658,12346659,12346660,12346661,12346662,12346663,12346664,12346665,12346666,12346667,12346668,12346669,12346670,12346671,12346672,12346673,12346674,12346675,12346676,12346677,12346678} -(1 row) - -reset default_toast_compression; +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/arrays.out C:/cirrus/build/testrun/regress/regress/results/arrays.out --- C:/cirrus/src/test/regress/expected/arrays.out 2024-03-20 22:41:28.840772800 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/arrays.out 2024-03-20 22:44:01.652405300 +0000 @@ -1,2701 +1,2 @@ --- --- ARRAYS --- --- directory paths are passed to us in environment variables -\getenv abs_srcdir PG_ABS_SRCDIR -CREATE TABLE arrtest ( - a int2[], - b int4[][][], - c name[], - d text[][], - e float8[], - f char(5)[], - g varchar(5)[] -); -CREATE TABLE array_op_test ( - seqno int4, - i int4[], - t text[] -); -\set filename :abs_srcdir '/data/array.data' -COPY array_op_test FROM :'filename'; -ANALYZE array_op_test; --- --- only the 'e' array is 0-based, the others are 1-based. --- -INSERT INTO arrtest (a[1:5], b[1:1][1:2][1:2], c, d, f, g) - VALUES ('{1,2,3,4,5}', '{{{0,0},{1,2}}}', '{}', '{}', '{}', '{}'); -UPDATE arrtest SET e[0] = '1.1'; -UPDATE arrtest SET e[1] = '2.2'; -INSERT INTO arrtest (f) - VALUES ('{"too long"}'); -ERROR: value too long for type character(5) -INSERT INTO arrtest (a, b[1:2][1:2], c, d, e, f, g) - VALUES ('{11,12,23}', '{{3,4},{4,5}}', '{"foobar"}', - '{{"elt1", "elt2"}}', '{"3.4", "6.7"}', - '{"abc","abcde"}', '{"abc","abcde"}'); -INSERT INTO arrtest (a, b[1:2], c, d[1:2]) - VALUES ('{}', '{3,4}', '{foo,bar}', '{bar,foo}'); -INSERT INTO arrtest (b[2]) VALUES(now()); -- error, type mismatch -ERROR: subscripted assignment to "b" requires type integer but expression is of type timestamp with time zone -LINE 1: INSERT INTO arrtest (b[2]) VALUES(now()); - ^ -HINT: You will need to rewrite or cast the expression. -INSERT INTO arrtest (b[1:2]) VALUES(now()); -- error, type mismatch -ERROR: subscripted assignment to "b" requires type integer[] but expression is of type timestamp with time zone -LINE 1: INSERT INTO arrtest (b[1:2]) VALUES(now()); - ^ -HINT: You will need to rewrite or cast the expression. -SELECT * FROM arrtest; - a | b | c | d | e | f | g --------------+-----------------+-----------+---------------+-----------------+-----------------+------------- - {1,2,3,4,5} | {{{0,0},{1,2}}} | {} | {} | [0:1]={1.1,2.2} | {} | {} - {11,12,23} | {{3,4},{4,5}} | {foobar} | {{elt1,elt2}} | {3.4,6.7} | {"abc ",abcde} | {abc,abcde} - {} | {3,4} | {foo,bar} | {bar,foo} | | | -(3 rows) - -SELECT arrtest.a[1], - arrtest.b[1][1][1], - arrtest.c[1], - arrtest.d[1][1], - arrtest.e[0] - FROM arrtest; - a | b | c | d | e -----+---+--------+------+----- - 1 | 0 | | | 1.1 - 11 | | foobar | elt1 | - | | foo | | -(3 rows) - -SELECT a[1], b[1][1][1], c[1], d[1][1], e[0] - FROM arrtest; - a | b | c | d | e -----+---+--------+------+----- - 1 | 0 | | | 1.1 - 11 | | foobar | elt1 | - | | foo | | -(3 rows) - -SELECT a[1:3], - b[1:1][1:2][1:2], - c[1:2], - d[1:1][1:2] - FROM arrtest; - a | b | c | d -------------+-----------------+-----------+--------------- - {1,2,3} | {{{0,0},{1,2}}} | {} | {} - {11,12,23} | {} | {foobar} | {{elt1,elt2}} - {} | {} | {foo,bar} | {} -(3 rows) - -SELECT array_ndims(a) AS a,array_ndims(b) AS b,array_ndims(c) AS c - FROM arrtest; - a | b | c ----+---+--- - 1 | 3 | - 1 | 2 | 1 - | 1 | 1 -(3 rows) - -SELECT array_dims(a) AS a,array_dims(b) AS b,array_dims(c) AS c - FROM arrtest; - a | b | c --------+-----------------+------- - [1:5] | [1:1][1:2][1:2] | - [1:3] | [1:2][1:2] | [1:1] - | [1:2] | [1:2] -(3 rows) - --- returns nothing -SELECT * - FROM arrtest - WHERE a[1] < 5 and - c = '{"foobar"}'::_name; - a | b | c | d | e | f | g ----+---+---+---+---+---+--- -(0 rows) - -UPDATE arrtest - SET a[1:2] = '{16,25}' - WHERE NOT a = '{}'::_int2; -UPDATE arrtest - SET b[1:1][1:1][1:2] = '{113, 117}', - b[1:1][1:2][2:2] = '{142, 147}' - WHERE array_dims(b) = '[1:1][1:2][1:2]'; -UPDATE arrtest - SET c[2:2] = '{"new_word"}' - WHERE array_dims(c) is not null; -SELECT a,b,c FROM arrtest; - a | b | c ----------------+-----------------------+------------------- - {16,25,3,4,5} | {{{113,142},{1,147}}} | {} - {} | {3,4} | {foo,new_word} - {16,25,23} | {{3,4},{4,5}} | {foobar,new_word} -(3 rows) - -SELECT a[1:3], - b[1:1][1:2][1:2], - c[1:2], - d[1:1][2:2] - FROM arrtest; - a | b | c | d -------------+-----------------------+-------------------+---------- - {16,25,3} | {{{113,142},{1,147}}} | {} | {} - {} | {} | {foo,new_word} | {} - {16,25,23} | {} | {foobar,new_word} | {{elt2}} -(3 rows) - -SELECT b[1:1][2][2], - d[1:1][2] - FROM arrtest; - b | d ------------------------+--------------- - {{{113,142},{1,147}}} | {} - {} | {} - {} | {{elt1,elt2}} -(3 rows) - -INSERT INTO arrtest(a) VALUES('{1,null,3}'); -SELECT a FROM arrtest; - a ---------------- - {16,25,3,4,5} - {} - {16,25,23} - {1,NULL,3} -(4 rows) - -UPDATE arrtest SET a[4] = NULL WHERE a[2] IS NULL; -SELECT a FROM arrtest WHERE a[2] IS NULL; - a ------------------ - [4:4]={NULL} - {1,NULL,3,NULL} -(2 rows) - -DELETE FROM arrtest WHERE a[2] IS NULL AND b IS NULL; -SELECT a,b,c FROM arrtest; - a | b | c ----------------+-----------------------+------------------- - {16,25,3,4,5} | {{{113,142},{1,147}}} | {} - {16,25,23} | {{3,4},{4,5}} | {foobar,new_word} - [4:4]={NULL} | {3,4} | {foo,new_word} -(3 rows) - --- test non-error-throwing API -SELECT pg_input_is_valid('{1,2,3}', 'integer[]'); - pg_input_is_valid -------------------- - t -(1 row) - -SELECT pg_input_is_valid('{1,2', 'integer[]'); - pg_input_is_valid -------------------- - f -(1 row) - -SELECT pg_input_is_valid('{1,zed}', 'integer[]'); - pg_input_is_valid -------------------- - f -(1 row) - -SELECT * FROM pg_input_error_info('{1,zed}', 'integer[]'); - message | detail | hint | sql_error_code -----------------------------------------------+--------+------+---------------- - invalid input syntax for type integer: "zed" | | | 22P02 -(1 row) - --- test mixed slice/scalar subscripting -select '{{1,2,3},{4,5,6},{7,8,9}}'::int[]; - int4 ---------------------------- - {{1,2,3},{4,5,6},{7,8,9}} -(1 row) - -select ('{{1,2,3},{4,5,6},{7,8,9}}'::int[])[1:2][2]; - int4 ---------------- - {{1,2},{4,5}} -(1 row) - -select '[0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}}'::int[]; - int4 --------------------------------------- - [0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}} -(1 row) - -select ('[0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}}'::int[])[1:2][2]; - int4 ---------------- - {{5,6},{8,9}} -(1 row) - --- --- check subscription corner cases --- --- More subscripts than MAXDIM (6) -SELECT ('{}'::int[])[1][2][3][4][5][6][7]; -ERROR: number of array dimensions (7) exceeds the maximum allowed (6) --- NULL index yields NULL when selecting -SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL][1]; - int4 ------- - -(1 row) - -SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][NULL:1][1]; - int4 ------- - -(1 row) - -SELECT ('{{{1},{2},{3}},{{4},{5},{6}}}'::int[])[1][1:NULL][1]; - int4 ------- - -(1 row) - --- NULL index in assignment is an error -UPDATE arrtest - SET c[NULL] = '{"can''t assign"}' - WHERE array_dims(c) is not null; -ERROR: array subscript in assignment must not be null -UPDATE arrtest - SET c[NULL:1] = '{"can''t assign"}' - WHERE array_dims(c) is not null; -ERROR: array subscript in assignment must not be null -UPDATE arrtest - SET c[1:NULL] = '{"can''t assign"}' - WHERE array_dims(c) is not null; -ERROR: array subscript in assignment must not be null --- Un-subscriptable type -SELECT (now())[1]; -ERROR: cannot subscript type timestamp with time zone because it does not support subscripting -LINE 1: SELECT (now())[1]; - ^ --- test slices with empty lower and/or upper index -CREATE TEMP TABLE arrtest_s ( - a int2[], - b int2[][] -); -INSERT INTO arrtest_s VALUES ('{1,2,3,4,5}', '{{1,2,3}, {4,5,6}, {7,8,9}}'); -INSERT INTO arrtest_s VALUES ('[0:4]={1,2,3,4,5}', '[0:2][0:2]={{1,2,3}, {4,5,6}, {7,8,9}}'); -SELECT * FROM arrtest_s; - a | b --------------------+-------------------------------------- - {1,2,3,4,5} | {{1,2,3},{4,5,6},{7,8,9}} - [0:4]={1,2,3,4,5} | [0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}} -(2 rows) - -SELECT a[:3], b[:2][:2] FROM arrtest_s; - a | b ------------+--------------------------- - {1,2,3} | {{1,2},{4,5}} - {1,2,3,4} | {{1,2,3},{4,5,6},{7,8,9}} -(2 rows) - -SELECT a[2:], b[2:][2:] FROM arrtest_s; - a | b ------------+--------------- - {2,3,4,5} | {{5,6},{8,9}} - {3,4,5} | {{9}} -(2 rows) - -SELECT a[:], b[:] FROM arrtest_s; - a | b --------------+--------------------------- - {1,2,3,4,5} | {{1,2,3},{4,5,6},{7,8,9}} - {1,2,3,4,5} | {{1,2,3},{4,5,6},{7,8,9}} -(2 rows) - --- updates -UPDATE arrtest_s SET a[:3] = '{11, 12, 13}', b[:2][:2] = '{{11,12}, {14,15}}' - WHERE array_lower(a,1) = 1; -SELECT * FROM arrtest_s; - a | b --------------------+-------------------------------------- - [0:4]={1,2,3,4,5} | [0:2][0:2]={{1,2,3},{4,5,6},{7,8,9}} - {11,12,13,4,5} | {{11,12,3},{14,15,6},{7,8,9}} -(2 rows) - -UPDATE arrtest_s SET a[3:] = '{23, 24, 25}', b[2:][2:] = '{{25,26}, {28,29}}'; -SELECT * FROM arrtest_s; - a | b ----------------------+--------------------------------------- - [0:4]={1,2,3,23,24} | [0:2][0:2]={{1,2,3},{4,5,6},{7,8,25}} - {11,12,23,24,25} | {{11,12,3},{14,25,26},{7,28,29}} -(2 rows) - -UPDATE arrtest_s SET a[:] = '{11, 12, 13, 14, 15}'; -SELECT * FROM arrtest_s; - a | b -------------------------+--------------------------------------- - [0:4]={11,12,13,14,15} | [0:2][0:2]={{1,2,3},{4,5,6},{7,8,25}} - {11,12,13,14,15} | {{11,12,3},{14,25,26},{7,28,29}} -(2 rows) - -UPDATE arrtest_s SET a[:] = '{23, 24, 25}'; -- fail, too small -ERROR: source array too small -INSERT INTO arrtest_s VALUES(NULL, NULL); -UPDATE arrtest_s SET a[:] = '{11, 12, 13, 14, 15}'; -- fail, no good with null -ERROR: array slice subscript must provide both boundaries -DETAIL: When assigning to a slice of an empty array value, slice boundaries must be fully specified. --- we want to work with a point_tbl that includes a null -CREATE TEMP TABLE point_tbl AS SELECT * FROM public.point_tbl; -INSERT INTO POINT_TBL(f1) VALUES (NULL); --- check with fixed-length-array type, such as point -SELECT f1[0:1] FROM POINT_TBL; -ERROR: slices of fixed-length arrays not implemented -SELECT f1[0:] FROM POINT_TBL; -ERROR: slices of fixed-length arrays not implemented -SELECT f1[:1] FROM POINT_TBL; -ERROR: slices of fixed-length arrays not implemented -SELECT f1[:] FROM POINT_TBL; -ERROR: slices of fixed-length arrays not implemented --- subscript assignments to fixed-width result in NULL if previous value is NULL -UPDATE point_tbl SET f1[0] = 10 WHERE f1 IS NULL RETURNING *; - f1 ----- - -(1 row) - -INSERT INTO point_tbl(f1[0]) VALUES(0) RETURNING *; - f1 ----- - -(1 row) - --- NULL assignments get ignored -UPDATE point_tbl SET f1[0] = NULL WHERE f1::text = '(10,10)'::point::text RETURNING *; - f1 ---------- - (10,10) -(1 row) - --- but non-NULL subscript assignments work -UPDATE point_tbl SET f1[0] = -10, f1[1] = -10 WHERE f1::text = '(10,10)'::point::text RETURNING *; - f1 ------------ - (-10,-10) -(1 row) - --- but not to expand the range -UPDATE point_tbl SET f1[3] = 10 WHERE f1::text = '(-10,-10)'::point::text RETURNING *; -ERROR: array subscript out of range --- --- test array extension --- -CREATE TEMP TABLE arrtest1 (i int[], t text[]); -insert into arrtest1 values(array[1,2,null,4], array['one','two',null,'four']); -select * from arrtest1; - i | t ---------------+--------------------- - {1,2,NULL,4} | {one,two,NULL,four} -(1 row) - -update arrtest1 set i[2] = 22, t[2] = 'twenty-two'; -select * from arrtest1; - i | t ----------------+---------------------------- - {1,22,NULL,4} | {one,twenty-two,NULL,four} -(1 row) - -update arrtest1 set i[5] = 5, t[5] = 'five'; -select * from arrtest1; - i | t ------------------+--------------------------------- - {1,22,NULL,4,5} | {one,twenty-two,NULL,four,five} -(1 row) - -update arrtest1 set i[8] = 8, t[8] = 'eight'; -select * from arrtest1; - i | t ------------------------------+------------------------------------------------- - {1,22,NULL,4,5,NULL,NULL,8} | {one,twenty-two,NULL,four,five,NULL,NULL,eight} -(1 row) - -update arrtest1 set i[0] = 0, t[0] = 'zero'; -select * from arrtest1; - i | t --------------------------------------+------------------------------------------------------------ - [0:8]={0,1,22,NULL,4,5,NULL,NULL,8} | [0:8]={zero,one,twenty-two,NULL,four,five,NULL,NULL,eight} -(1 row) - -update arrtest1 set i[-3] = -3, t[-3] = 'minus-three'; -select * from arrtest1; - i | t ----------------------------------------------------+----------------------------------------------------------------------------------- - [-3:8]={-3,NULL,NULL,0,1,22,NULL,4,5,NULL,NULL,8} | [-3:8]={minus-three,NULL,NULL,zero,one,twenty-two,NULL,four,five,NULL,NULL,eight} -(1 row) - -update arrtest1 set i[0:2] = array[10,11,12], t[0:2] = array['ten','eleven','twelve']; -select * from arrtest1; - i | t ------------------------------------------------------+--------------------------------------------------------------------------------- - [-3:8]={-3,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,8} | [-3:8]={minus-three,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,eight} -(1 row) - -update arrtest1 set i[8:10] = array[18,null,20], t[8:10] = array['p18',null,'p20']; -select * from arrtest1; - i | t ----------------------------------------------------------------+----------------------------------------------------------------------------------------- - [-3:10]={-3,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,18,NULL,20} | [-3:10]={minus-three,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,p18,NULL,p20} -(1 row) - -update arrtest1 set i[11:12] = array[null,22], t[11:12] = array[null,'p22']; -select * from arrtest1; - i | t ------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------- - [-3:12]={-3,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,18,NULL,20,NULL,22} | [-3:12]={minus-three,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,p18,NULL,p20,NULL,p22} -(1 row) - -update arrtest1 set i[15:16] = array[null,26], t[15:16] = array[null,'p26']; -select * from arrtest1; - i | t ------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------- - [-3:16]={-3,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,18,NULL,20,NULL,22,NULL,NULL,NULL,26} | [-3:16]={minus-three,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,p18,NULL,p20,NULL,p22,NULL,NULL,NULL,p26} -(1 row) - -update arrtest1 set i[-5:-3] = array[-15,-14,-13], t[-5:-3] = array['m15','m14','m13']; -select * from arrtest1; - i | t ---------------------------------------------------------------------------------------------------+--------------------------------------------------------------------------------------------------------------------- - [-5:16]={-15,-14,-13,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,18,NULL,20,NULL,22,NULL,NULL,NULL,26} | [-5:16]={m15,m14,m13,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,p18,NULL,p20,NULL,p22,NULL,NULL,NULL,p26} -(1 row) - -update arrtest1 set i[-7:-6] = array[-17,null], t[-7:-6] = array['m17',null]; -select * from arrtest1; - i | t ------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------ - [-7:16]={-17,NULL,-15,-14,-13,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,18,NULL,20,NULL,22,NULL,NULL,NULL,26} | [-7:16]={m17,NULL,m15,m14,m13,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,p18,NULL,p20,NULL,p22,NULL,NULL,NULL,p26} -(1 row) - -update arrtest1 set i[-12:-10] = array[-22,null,-20], t[-12:-10] = array['m22',null,'m20']; -select * from arrtest1; - i | t ------------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------------------------------------ - [-12:16]={-22,NULL,-20,NULL,NULL,-17,NULL,-15,-14,-13,NULL,NULL,10,11,12,NULL,4,5,NULL,NULL,18,NULL,20,NULL,22,NULL,NULL,NULL,26} | [-12:16]={m22,NULL,m20,NULL,NULL,m17,NULL,m15,m14,m13,NULL,NULL,ten,eleven,twelve,NULL,four,five,NULL,NULL,p18,NULL,p20,NULL,p22,NULL,NULL,NULL,p26} -(1 row) - -delete from arrtest1; -insert into arrtest1 values(array[1,2,null,4], array['one','two',null,'four']); -select * from arrtest1; - i | t ---------------+--------------------- - {1,2,NULL,4} | {one,two,NULL,four} -(1 row) - -update arrtest1 set i[0:5] = array[0,1,2,null,4,5], t[0:5] = array['z','p1','p2',null,'p4','p5']; -select * from arrtest1; - i | t -------------------------+---------------------------- - [0:5]={0,1,2,NULL,4,5} | [0:5]={z,p1,p2,NULL,p4,p5} -(1 row) - --- --- array expressions and operators --- --- table creation and INSERTs -CREATE TEMP TABLE arrtest2 (i integer ARRAY[4], f float8[], n numeric[], t text[], d timestamp[]); -INSERT INTO arrtest2 VALUES( - ARRAY[[[113,142],[1,147]]], - ARRAY[1.1,1.2,1.3]::float8[], - ARRAY[1.1,1.2,1.3], - ARRAY[[['aaa','aab'],['aba','abb'],['aca','acb']],[['baa','bab'],['bba','bbb'],['bca','bcb']]], - ARRAY['19620326','19931223','19970117']::timestamp[] -); --- some more test data -CREATE TEMP TABLE arrtest_f (f0 int, f1 text, f2 float8); -insert into arrtest_f values(1,'cat1',1.21); -insert into arrtest_f values(2,'cat1',1.24); -insert into arrtest_f values(3,'cat1',1.18); -insert into arrtest_f values(4,'cat1',1.26); -insert into arrtest_f values(5,'cat1',1.15); -insert into arrtest_f values(6,'cat2',1.15); -insert into arrtest_f values(7,'cat2',1.26); -insert into arrtest_f values(8,'cat2',1.32); -insert into arrtest_f values(9,'cat2',1.30); -CREATE TEMP TABLE arrtest_i (f0 int, f1 text, f2 int); -insert into arrtest_i values(1,'cat1',21); -insert into arrtest_i values(2,'cat1',24); -insert into arrtest_i values(3,'cat1',18); -insert into arrtest_i values(4,'cat1',26); -insert into arrtest_i values(5,'cat1',15); -insert into arrtest_i values(6,'cat2',15); -insert into arrtest_i values(7,'cat2',26); -insert into arrtest_i values(8,'cat2',32); -insert into arrtest_i values(9,'cat2',30); --- expressions -SELECT t.f[1][3][1] AS "131", t.f[2][2][1] AS "221" FROM ( - SELECT ARRAY[[[111,112],[121,122],[131,132]],[[211,212],[221,122],[231,232]]] AS f -) AS t; - 131 | 221 ------+----- - 131 | 221 -(1 row) - -SELECT ARRAY[[[[[['hello'],['world']]]]]]; - array ---------------------------- - {{{{{{hello},{world}}}}}} -(1 row) - -SELECT ARRAY[ARRAY['hello'],ARRAY['world']]; - array -------------------- - {{hello},{world}} -(1 row) - -SELECT ARRAY(select f2 from arrtest_f order by f2) AS "ARRAY"; - ARRAY ------------------------------------------------ - {1.15,1.15,1.18,1.21,1.24,1.26,1.26,1.3,1.32} -(1 row) - --- with nulls -SELECT '{1,null,3}'::int[]; - int4 ------------- - {1,NULL,3} -(1 row) - -SELECT ARRAY[1,NULL,3]; - array ------------- - {1,NULL,3} -(1 row) - --- functions -SELECT array_append(array[42], 6) AS "{42,6}"; - {42,6} --------- - {42,6} -(1 row) - -SELECT array_prepend(6, array[42]) AS "{6,42}"; - {6,42} --------- - {6,42} -(1 row) - -SELECT array_cat(ARRAY[1,2], ARRAY[3,4]) AS "{1,2,3,4}"; - {1,2,3,4} ------------ - {1,2,3,4} -(1 row) - -SELECT array_cat(ARRAY[1,2], ARRAY[[3,4],[5,6]]) AS "{{1,2},{3,4},{5,6}}"; - {{1,2},{3,4},{5,6}} ---------------------- - {{1,2},{3,4},{5,6}} -(1 row) - -SELECT array_cat(ARRAY[[3,4],[5,6]], ARRAY[1,2]) AS "{{3,4},{5,6},{1,2}}"; - {{3,4},{5,6},{1,2}} ---------------------- - {{3,4},{5,6},{1,2}} -(1 row) - -SELECT array_position(ARRAY[1,2,3,4,5], 4); - array_position ----------------- - 4 -(1 row) - -SELECT array_position(ARRAY[5,3,4,2,1], 4); - array_position ----------------- - 3 -(1 row) - -SELECT array_position(ARRAY[[1,2],[3,4]], 3); -ERROR: searching for elements in multidimensional arrays is not supported -SELECT array_position(ARRAY['sun','mon','tue','wed','thu','fri','sat'], 'mon'); - array_position ----------------- - 2 -(1 row) - -SELECT array_position(ARRAY['sun','mon','tue','wed','thu','fri','sat'], 'sat'); - array_position ----------------- - 7 -(1 row) - -SELECT array_position(ARRAY['sun','mon','tue','wed','thu','fri','sat'], NULL); - array_position ----------------- - -(1 row) - -SELECT array_position(ARRAY['sun','mon','tue','wed','thu',NULL,'fri','sat'], NULL); - array_position ----------------- - 6 -(1 row) - -SELECT array_position(ARRAY['sun','mon','tue','wed','thu',NULL,'fri','sat'], 'sat'); - array_position ----------------- - 8 -(1 row) - -SELECT array_positions(NULL, 10); - array_positions ------------------ - -(1 row) - -SELECT array_positions(NULL, NULL::int); - array_positions ------------------ - -(1 row) - -SELECT array_positions(ARRAY[1,2,3,4,5,6,1,2,3,4,5,6], 4); - array_positions ------------------ - {4,10} -(1 row) - -SELECT array_positions(ARRAY[[1,2],[3,4]], 4); -ERROR: searching for elements in multidimensional arrays is not supported -SELECT array_positions(ARRAY[1,2,3,4,5,6,1,2,3,4,5,6], NULL); - array_positions ------------------ - {} -(1 row) - -SELECT array_positions(ARRAY[1,2,3,NULL,5,6,1,2,3,NULL,5,6], NULL); - array_positions ------------------ - {4,10} -(1 row) - -SELECT array_length(array_positions(ARRAY(SELECT 'AAAAAAAAAAAAAAAAAAAAAAAAA'::text || i % 10 - FROM generate_series(1,100) g(i)), - 'AAAAAAAAAAAAAAAAAAAAAAAAA5'), 1); - array_length --------------- - 10 -(1 row) - -DO $$ -DECLARE - o int; - a int[] := ARRAY[1,2,3,2,3,1,2]; -BEGIN - o := array_position(a, 2); - WHILE o IS NOT NULL - LOOP - RAISE NOTICE '%', o; - o := array_position(a, 2, o + 1); - END LOOP; -END -$$ LANGUAGE plpgsql; -NOTICE: 2 -NOTICE: 4 -NOTICE: 7 -SELECT array_position('[2:4]={1,2,3}'::int[], 1); - array_position ----------------- - 2 -(1 row) - -SELECT array_positions('[2:4]={1,2,3}'::int[], 1); - array_positions ------------------ - {2} -(1 row) - -SELECT - array_position(ids, (1, 1)), - array_positions(ids, (1, 1)) - FROM -(VALUES - (ARRAY[(0, 0), (1, 1)]), - (ARRAY[(1, 1)]) -) AS f (ids); - array_position | array_positions -----------------+----------------- - 2 | {2} - 1 | {1} -(2 rows) - --- operators -SELECT a FROM arrtest WHERE b = ARRAY[[[113,142],[1,147]]]; - a ---------------- - {16,25,3,4,5} -(1 row) - -SELECT NOT ARRAY[1.1,1.2,1.3] = ARRAY[1.1,1.2,1.3] AS "FALSE"; - FALSE -------- - f -(1 row) - -SELECT ARRAY[1,2] || 3 AS "{1,2,3}"; - {1,2,3} ---------- - {1,2,3} -(1 row) - -SELECT 0 || ARRAY[1,2] AS "{0,1,2}"; - {0,1,2} ---------- - {0,1,2} -(1 row) - -SELECT ARRAY[1,2] || ARRAY[3,4] AS "{1,2,3,4}"; - {1,2,3,4} ------------ - {1,2,3,4} -(1 row) - -SELECT ARRAY[[['hello','world']]] || ARRAY[[['happy','birthday']]] AS "ARRAY"; - ARRAY --------------------------------------- - {{{hello,world}},{{happy,birthday}}} -(1 row) - -SELECT ARRAY[[1,2],[3,4]] || ARRAY[5,6] AS "{{1,2},{3,4},{5,6}}"; - {{1,2},{3,4},{5,6}} ---------------------- - {{1,2},{3,4},{5,6}} -(1 row) - -SELECT ARRAY[0,0] || ARRAY[1,1] || ARRAY[2,2] AS "{0,0,1,1,2,2}"; - {0,0,1,1,2,2} ---------------- - {0,0,1,1,2,2} -(1 row) - -SELECT 0 || ARRAY[1,2] || 3 AS "{0,1,2,3}"; - {0,1,2,3} ------------ - {0,1,2,3} -(1 row) - -SELECT ARRAY[1.1] || ARRAY[2,3,4]; - ?column? -------------- - {1.1,2,3,4} -(1 row) - -SELECT array_agg(x) || array_agg(x) FROM (VALUES (ROW(1,2)), (ROW(3,4))) v(x); - ?column? ------------------------------------ - {"(1,2)","(3,4)","(1,2)","(3,4)"} -(1 row) - -SELECT ROW(1,2) || array_agg(x) FROM (VALUES (ROW(3,4)), (ROW(5,6))) v(x); - ?column? ---------------------------- - {"(1,2)","(3,4)","(5,6)"} -(1 row) - -SELECT * FROM array_op_test WHERE i @> '{32}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} - 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} - 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} -(6 rows) - -SELECT * FROM array_op_test WHERE i && '{32}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} - 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} - 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} -(6 rows) - -SELECT * FROM array_op_test WHERE i @> '{17}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} - 53 | {38,17} | {AAAAAAAAAAA21658} - 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} -(8 rows) - -SELECT * FROM array_op_test WHERE i && '{17}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} - 53 | {38,17} | {AAAAAAAAAAA21658} - 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} -(8 rows) - -SELECT * FROM array_op_test WHERE i @> '{32,17}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} -(3 rows) - -SELECT * FROM array_op_test WHERE i && '{32,17}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} - 53 | {38,17} | {AAAAAAAAAAA21658} - 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} - 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} - 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} - 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} -(11 rows) - -SELECT * FROM array_op_test WHERE i <@ '{38,34,32,89}' ORDER BY seqno; - seqno | i | t --------+---------------+---------------------------------------------------------------------------------------------------------------------------- - 40 | {34} | {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623} - 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} - 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} - 101 | {} | {} -(4 rows) - -SELECT * FROM array_op_test WHERE i = '{}' ORDER BY seqno; - seqno | i | t --------+----+---- - 101 | {} | {} -(1 row) - -SELECT * FROM array_op_test WHERE i @> '{}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 1 | {92,75,71,52,64,83} | {AAAAAAAA44066,AAAAAA1059,AAAAAAAAAAA176,AAAAAAA48038} - 2 | {3,6} | {AAAAAA98232,AAAAAAAA79710,AAAAAAAAAAAAAAAAA69675,AAAAAAAAAAAAAAAA55798,AAAAAAAAA12793} - 3 | {37,64,95,43,3,41,13,30,11,43} | {AAAAAAAAAA48845,AAAAA75968,AAAAA95309,AAA54451,AAAAAAAAAA22292,AAAAAAA99836,A96617,AA17009,AAAAAAAAAAAAAA95246} - 4 | {71,39,99,55,33,75,45} | {AAAAAAAAA53663,AAAAAAAAAAAAAAA67062,AAAAAAAAAA64777,AAA99043,AAAAAAAAAAAAAAAAAAA91804,39557} - 5 | {50,42,77,50,4} | {AAAAAAAAAAAAAAAAA26540,AAAAAAA79710,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA176,AAAAA95309,AAAAAAAAAAA46154,AAAAAA66777,AAAAAAAAA27249,AAAAAAAAAA64777,AAAAAAAAAAAAAAAAAAA70104} - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 7 | {12,51,88,64,8} | {AAAAAAAAAAAAAAAAAA12591,AAAAAAAAAAAAAAAAA50407,AAAAAAAAAAAA67946} - 8 | {60,84} | {AAAAAAA81898,AAAAAA1059,AAAAAAAAAAAA81511,AAAAA961,AAAAAAAAAAAAAAAA31334,AAAAA64741,AA6416,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAAAA50407} - 9 | {56,52,35,27,80,44,81,22} | {AAAAAAAAAAAAAAA73034,AAAAAAAAAAAAA7929,AAAAAAA66161,AA88409,39557,A27153,AAAAAAAA9523,AAAAAAAAAAA99000} - 10 | {71,5,45} | {AAAAAAAAAAA21658,AAAAAAAAAAAA21089,AAA54451,AAAAAAAAAAAAAAAAAA54141,AAAAAAAAAAAAAA28620,AAAAAAAAAAA21658,AAAAAAAAAAA74076,AAAAAAAAA27249} - 11 | {41,86,74,48,22,74,47,50} | {AAAAAAAA9523,AAAAAAAAAAAA37562,AAAAAAAAAAAAAAAA14047,AAAAAAAAAAA46154,AAAA41702,AAAAAAAAAAAAAAAAA764,AAAAA62737,39557} - 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} - 13 | {3,52,34,23} | {AAAAAA98232,AAAA49534,AAAAAAAAAAA21658} - 14 | {78,57,19} | {AAAA8857,AAAAAAAAAAAAAAA73034,AAAAAAAA81587,AAAAAAAAAAAAAAA68526,AAAAA75968,AAAAAAAAAAAAAA65909,AAAAAAAAA10012,AAAAAAAAAAAAAA65909} - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 16 | {14,63,85,11} | {AAAAAA66777} - 17 | {7,10,81,85} | {AAAAAA43678,AAAAAAA12144,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAAAAA15356} - 18 | {1} | {AAAAAAAAAAA33576,AAAAA95309,64261,AAA59323,AAAAAAAAAAAAAA95246,55847,AAAAAAAAAAAA67946,AAAAAAAAAAAAAAAAAA64374} - 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} - 20 | {72,89,70,51,54,37,8,49,79} | {AAAAAA58494} - 21 | {2,8,65,10,5,79,43} | {AAAAAAAAAAAAAAAAA88852,AAAAAAAAAAAAAAAAAAA91804,AAAAA64669,AAAAAAAAAAAAAAAA1443,AAAAAAAAAAAAAAAA23657,AAAAA12179,AAAAAAAAAAAAAAAAA88852,AAAAAAAAAAAAAAAA31334,AAAAAAAAAAAAAAAA41303,AAAAAAAAAAAAAAAAAAA85420} - 22 | {11,6,56,62,53,30} | {AAAAAAAA72908} - 23 | {40,90,5,38,72,40,30,10,43,55} | {A6053,AAAAAAAAAAA6119,AA44673,AAAAAAAAAAAAAAAAA764,AA17009,AAAAA17383,AAAAA70514,AAAAA33250,AAAAA95309,AAAAAAAAAAAA37562} - 24 | {94,61,99,35,48} | {AAAAAAAAAAA50956,AAAAAAAAAAA15165,AAAA85070,AAAAAAAAAAAAAAA36627,AAAAA961,AAAAAAAAAA55219} - 25 | {31,1,10,11,27,79,38} | {AAAAAAAAAAAAAAAAAA59334,45449} - 26 | {71,10,9,69,75} | {47735,AAAAAAA21462,AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAAAAA91804,AAAAAAAAA72121,AAAAAAAAAAAAAAAAAAA1205,AAAAA41597,AAAA8857,AAAAAAAAAAAAAAAAAAA15356,AA17009} - 27 | {94} | {AA6416,A6053,AAAAAAA21462,AAAAAAA57334,AAAAAAAAAAAAAAAAAA12591,AA88409,AAAAAAAAAAAAA70254} - 28 | {14,33,6,34,14} | {AAAAAAAAAAAAAAA13198,AAAAAAAA69452,AAAAAAAAAAA82945,AAAAAAA12144,AAAAAAAAA72121,AAAAAAAAAA18601} - 29 | {39,21} | {AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAAAAA38885,AAAA85070,AAAAAAAAAAAAAAAAAAA70104,AAAAA66674,AAAAAAAAAAAAA62007,AAAAAAAA69452,AAAAAAA1242,AAAAAAAAAAAAAAAA1729,AAAA35194} - 30 | {26,81,47,91,34} | {AAAAAAAAAAAAAAAAAAA70104,AAAAAAA80240} - 31 | {80,24,18,21,54} | {AAAAAAAAAAAAAAA13198,AAAAAAAAAAAAAAAAAAA70415,A27153,AAAAAAAAA53663,AAAAAAAAAAAAAAAAA50407,A68938} - 32 | {58,79,82,80,67,75,98,10,41} | {AAAAAAAAAAAAAAAAAA61286,AAA54451,AAAAAAAAAAAAAAAAAAA87527,A96617,51533} - 33 | {74,73} | {A85417,AAAAAAA56483,AAAAA17383,AAAAAAAAAAAAA62159,AAAAAAAAAAAA52814,AAAAAAAAAAAAA85723,AAAAAAAAAAAAAAAAAA55796} - 34 | {70,45} | {AAAAAAAAAAAAAAAAAA71621,AAAAAAAAAAAAAA28620,AAAAAAAAAA55219,AAAAAAAA23648,AAAAAAAAAA22292,AAAAAAA1242} - 35 | {23,40} | {AAAAAAAAAAAA52814,AAAA48949,AAAAAAAAA34727,AAAA8857,AAAAAAAAAAAAAAAAAAA62179,AAAAAAAAAAAAAAA68526,AAAAAAA99836,AAAAAAAA50094,AAAA91194,AAAAAAAAAAAAA73084} - 36 | {79,82,14,52,30,5,79} | {AAAAAAAAA53663,AAAAAAAAAAAAAAAA55798,AAAAAAAAAAAAAAAAAAA89194,AA88409,AAAAAAAAAAAAAAA81326,AAAAAAAAAAAAAAAAA63050,AAAAAAAAAAAAAAAA33598} - 37 | {53,11,81,39,3,78,58,64,74} | {AAAAAAAAAAAAAAAAAAA17075,AAAAAAA66161,AAAAAAAA23648,AAAAAAAAAAAAAA10611} - 38 | {59,5,4,95,28} | {AAAAAAAAAAA82945,A96617,47735,AAAAA12179,AAAAA64669,AAAAAA99807,AA74433,AAAAAAAAAAAAAAAAA59387} - 39 | {82,43,99,16,74} | {AAAAAAAAAAAAAAA67062,AAAAAAA57334,AAAAAAAAAAAAAA65909,A27153,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAA64777,AAAAAAAAAAAA81511,AAAAAAAAAAAAAA65909,AAAAAAAAAAAAAA28620} - 40 | {34} | {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623} - 41 | {19,26,63,12,93,73,27,94} | {AAAAAAA79710,AAAAAAAAAA55219,AAAA41702,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAAA71621,AAAAAAAAAAAAAAAAA63050,AAAAAAA99836,AAAAAAAAAAAAAA8666} - 42 | {15,76,82,75,8,91} | {AAAAAAAAAAA176,AAAAAA38063,45449,AAAAAA54032,AAAAAAA81898,AA6416,AAAAAAAAAAAAAAAAAAA62179,45449,AAAAA60038,AAAAAAAA81587} - 43 | {39,87,91,97,79,28} | {AAAAAAAAAAA74076,A96617,AAAAAAAAAAAAAAAAAAA89194,AAAAAAAAAAAAAAAAAA55796,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAA67946} - 44 | {40,58,68,29,54} | {AAAAAAA81898,AAAAAA66777,AAAAAA98232} - 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611} - 46 | {53,24} | {AAAAAAAAAAA53908,AAAAAA54032,AAAAA17383,AAAA48949,AAAAAAAAAA18601,AAAAA64669,45449,AAAAAAAAAAA98051,AAAAAAAAAAAAAAAAAA71621} - 47 | {98,23,64,12,75,61} | {AAA59323,AAAAA95309,AAAAAAAAAAAAAAAA31334,AAAAAAAAA27249,AAAAA17383,AAAAAAAAAAAA37562,AAAAAA1059,A84822,55847,AAAAA70466} - 48 | {76,14} | {AAAAAAAAAAAAA59671,AAAAAAAAAAAAAAAAAAA91804,AAAAAA66777,AAAAAAAAAAAAAAAAAAA89194,AAAAAAAAAAAAAAA36627,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAA73084,AAAAAAA79710,AAAAAAAAAAAAAAA40402,AAAAAAAAAAAAAAAAAAA65037} - 49 | {56,5,54,37,49} | {AA21643,AAAAAAAAAAA92631,AAAAAAAA81587} - 50 | {20,12,37,64,93} | {AAAAAAAAAA5483,AAAAAAAAAAAAAAAAAAA1205,AA6416,AAAAAAAAAAAAAAAAA63050,AAAAAAAAAAAAAAAAAA47955} - 51 | {47} | {AAAAAAAAAAAAAA96505,AAAAAAAAAAAAAAAAAA36842,AAAAA95309,AAAAAAAA81587,AA6416,AAAA91194,AAAAAA58494,AAAAAA1059,AAAAAAAA69452} - 52 | {89,0} | {AAAAAAAAAAAAAAAAAA47955,AAAAAAA48038,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAAAAA73084,AAAAA70466,AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA46154,AA66862} - 53 | {38,17} | {AAAAAAAAAAA21658} - 54 | {70,47} | {AAAAAAAAAAAAAAAAAA54141,AAAAA40681,AAAAAAA48038,AAAAAAAAAAAAAAAA29150,AAAAA41597,AAAAAAAAAAAAAAAAAA59334,AA15322} - 55 | {47,79,47,64,72,25,71,24,93} | {AAAAAAAAAAAAAAAAAA55796,AAAAA62737} - 56 | {33,7,60,54,93,90,77,85,39} | {AAAAAAAAAAAAAAAAAA32918,AA42406} - 57 | {23,45,10,42,36,21,9,96} | {AAAAAAAAAAAAAAAAAAA70415} - 58 | {92} | {AAAAAAAAAAAAAAAA98414,AAAAAAAA23648,AAAAAAAAAAAAAAAAAA55796,AA25381,AAAAAAAAAAA6119} - 59 | {9,69,46,77} | {39557,AAAAAAA89932,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAAAAAAAAA26540,AAA20874,AA6416,AAAAAAAAAAAAAAAAAA47955} - 60 | {62,2,59,38,89} | {AAAAAAA89932,AAAAAAAAAAAAAAAAAAA15356,AA99927,AA17009,AAAAAAAAAAAAAAA35875} - 61 | {72,2,44,95,54,54,13} | {AAAAAAAAAAAAAAAAAAA91804} - 62 | {83,72,29,73} | {AAAAAAAAAAAAA15097,AAAA8857,AAAAAAAAAAAA35809,AAAAAAAAAAAA52814,AAAAAAAAAAAAAAAAAAA38885,AAAAAAAAAAAAAAAAAA24183,AAAAAA43678,A96617} - 63 | {11,4,61,87} | {AAAAAAAAA27249,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAA13198,AAA20874,39557,51533,AAAAAAAAAAA53908,AAAAAAAAAAAAAA96505,AAAAAAAA78938} - 64 | {26,19,34,24,81,78} | {A96617,AAAAAAAAAAAAAAAAAAA70104,A68938,AAAAAAAAAAA53908,AAAAAAAAAAAAAAA453,AA17009,AAAAAAA80240} - 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} - 66 | {31,23,70,52,4,33,48,25} | {AAAAAAAAAAAAAAAAA69675,AAAAAAAA50094,AAAAAAAAAAA92631,AAAA35194,39557,AAAAAAA99836} - 67 | {31,94,7,10} | {AAAAAA38063,A96617,AAAA35194,AAAAAAAAAAAA67946} - 68 | {90,43,38} | {AA75092,AAAAAAAAAAAAAAAAA69675,AAAAAAAAAAA92631,AAAAAAAAA10012,AAAAAAAAAAAAA7929,AA21643} - 69 | {67,35,99,85,72,86,44} | {AAAAAAAAAAAAAAAAAAA1205,AAAAAAAA50094,AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAAAAAAA47955} - 70 | {56,70,83} | {AAAA41702,AAAAAAAAAAA82945,AA21643,AAAAAAAAAAA99000,A27153,AA25381,AAAAAAAAAAAAAA96505,AAAAAAA1242} - 71 | {74,26} | {AAAAAAAAAAA50956,AA74433,AAAAAAA21462,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAA36627,AAAAAAAAAAAAA70254,AAAAAAAAAA43419,39557} - 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407} - 73 | {88,25,96,78,65,15,29,19} | {AAA54451,AAAAAAAAA27249,AAAAAAA9228,AAAAAAAAAAAAAAA67062,AAAAAAAAAAAAAAAAAAA70415,AAAAA17383,AAAAAAAAAAAAAAAA33598} - 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} - 75 | {12,96,83,24,71,89,55} | {AAAA48949,AAAAAAAA29716,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAAA67946,AAAAAAAAAAAAAAAA29150,AAA28075,AAAAAAAAAAAAAAAAA43052} - 76 | {92,55,10,7} | {AAAAAAAAAAAAAAA67062} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 78 | {55,89,44,84,34} | {AAAAAAAAAAA6119,AAAAAAAAAAAAAA8666,AA99927,AA42406,AAAAAAA81898,AAAAAAA9228,AAAAAAAAAAA92631,AA21643,AAAAAAAAAAAAAA28620} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} - 80 | {74,89,44,80,0} | {AAAA35194,AAAAAAAA79710,AAA20874,AAAAAAAAAAAAAAAAAAA70104,AAAAAAAAAAAAA73084,AAAAAAA57334,AAAAAAA9228,AAAAAAAAAAAAA62007} - 81 | {63,77,54,48,61,53,97} | {AAAAAAAAAAAAAAA81326,AAAAAAAAAA22292,AA25381,AAAAAAAAAAA74076,AAAAAAA81898,AAAAAAAAA72121} - 82 | {34,60,4,79,78,16,86,89,42,50} | {AAAAA40681,AAAAAAAAAAAAAAAAAA12591,AAAAAAA80240,AAAAAAAAAAAAAAAA55798,AAAAAAAAAAAAAAAAAAA70104} - 83 | {14,10} | {AAAAAAAAAA22292,AAAAAAAAAAAAA70254,AAAAAAAAAAA6119} - 84 | {11,83,35,13,96,94} | {AAAAA95309,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAAAAA24183} - 85 | {39,60} | {AAAAAAAAAAAAAAAA55798,AAAAAAAAAA22292,AAAAAAA66161,AAAAAAA21462,AAAAAAAAAAAAAAAAAA12591,55847,AAAAAA98232,AAAAAAAAAAA46154} - 86 | {33,81,72,74,45,36,82} | {AAAAAAAA81587,AAAAAAAAAAAAAA96505,45449,AAAA80176} - 87 | {57,27,50,12,97,68} | {AAAAAAAAAAAAAAAAA26540,AAAAAAAAA10012,AAAAAAAAAAAA35809,AAAAAAAAAAAAAAAA29150,AAAAAAAAAAA82945,AAAAAA66777,31228,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAA96505} - 88 | {41,90,77,24,6,24} | {AAAA35194,AAAA35194,AAAAAAA80240,AAAAAAAAAAA46154,AAAAAA58494,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAAA59334,AAAAAAAAAAAAAAAAAAA91804,AA74433} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} - 90 | {88,75} | {AAAAA60038,AAAAAAAA23648,AAAAAAAAAAA99000,AAAA41702,AAAAAAAAAAAAA22860,AAAAAAAAAAAAAAA68526} - 91 | {78} | {AAAAAAAAAAAAA62007,AAA99043} - 92 | {85,63,49,45} | {AAAAAAA89932,AAAAAAAAAAAAA22860,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAAA21089} - 93 | {11} | {AAAAAAAAAAA176,AAAAAAAAAAAAAA8666,AAAAAAAAAAAAAAA453,AAAAAAAAAAAAA85723,A68938,AAAAAAAAAAAAA9821,AAAAAAA48038,AAAAAAAAAAAAAAAAA59387,AA99927,AAAAA17383} - 94 | {98,9,85,62,88,91,60,61,38,86} | {AAAAAAAA81587,AAAAA17383,AAAAAAAA81587} - 95 | {47,77} | {AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA74076,AAAAAAAAAA18107,AAAAA40681,AAAAAAAAAAAAAAA35875,AAAAA60038,AAAAAAA56483} - 96 | {23,97,43} | {AAAAAAAAAA646,A87088} - 97 | {54,2,86,65} | {47735,AAAAAAA99836,AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAA29150,AAAAAAA80240,AAAAAAAAAAAAAAAA98414,AAAAAAA56483,AAAAAAAAAAAAAAAA29150,AAAAAAA39692,AA21643} - 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} - 99 | {37,86} | {AAAAAAAAAAAAAAAAAA32918,AAAAA70514,AAAAAAAAA10012,AAAAAAAAAAAAAAAAA59387,AAAAAAAAAA64777,AAAAAAAAAAAAAAAAAAA15356} - 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} - 101 | {} | {} - 102 | {NULL} | {NULL} -(102 rows) - -SELECT * FROM array_op_test WHERE i && '{}' ORDER BY seqno; - seqno | i | t --------+---+--- -(0 rows) - -SELECT * FROM array_op_test WHERE i <@ '{}' ORDER BY seqno; - seqno | i | t --------+----+---- - 101 | {} | {} -(1 row) - -SELECT * FROM array_op_test WHERE i = '{NULL}' ORDER BY seqno; - seqno | i | t --------+--------+-------- - 102 | {NULL} | {NULL} -(1 row) - -SELECT * FROM array_op_test WHERE i @> '{NULL}' ORDER BY seqno; - seqno | i | t --------+---+--- -(0 rows) - -SELECT * FROM array_op_test WHERE i && '{NULL}' ORDER BY seqno; - seqno | i | t --------+---+--- -(0 rows) - -SELECT * FROM array_op_test WHERE i <@ '{NULL}' ORDER BY seqno; - seqno | i | t --------+----+---- - 101 | {} | {} -(1 row) - -SELECT * FROM array_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; - seqno | i | t --------+-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------- - 22 | {11,6,56,62,53,30} | {AAAAAAAA72908} - 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611} - 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} -(4 rows) - -SELECT * FROM array_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno; - seqno | i | t --------+-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------- - 22 | {11,6,56,62,53,30} | {AAAAAAAA72908} - 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611} - 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} -(4 rows) - -SELECT * FROM array_op_test WHERE t @> '{AAAAAAAAAA646}' ORDER BY seqno; - seqno | i | t --------+------------------+-------------------------------------------------------------------- - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} - 96 | {23,97,43} | {AAAAAAAAAA646,A87088} -(3 rows) - -SELECT * FROM array_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno; - seqno | i | t --------+------------------+-------------------------------------------------------------------- - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} - 96 | {23,97,43} | {AAAAAAAAAA646,A87088} -(3 rows) - -SELECT * FROM array_op_test WHERE t @> '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno; - seqno | i | t --------+------+-------------------------------------------------------------------- - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} -(1 row) - -SELECT * FROM array_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno; - seqno | i | t --------+-----------------------+-------------------------------------------------------------------------------------------------------------------------------------------- - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 22 | {11,6,56,62,53,30} | {AAAAAAAA72908} - 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611} - 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} - 96 | {23,97,43} | {AAAAAAAAAA646,A87088} -(6 rows) - -SELECT * FROM array_op_test WHERE t <@ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno; - seqno | i | t --------+--------------------+----------------------------------------------------------------------------------------------------------- - 22 | {11,6,56,62,53,30} | {AAAAAAAA72908} - 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611} - 101 | {} | {} -(3 rows) - -SELECT * FROM array_op_test WHERE t = '{}' ORDER BY seqno; - seqno | i | t --------+----+---- - 101 | {} | {} -(1 row) - -SELECT * FROM array_op_test WHERE t @> '{}' ORDER BY seqno; - seqno | i | t --------+---------------------------------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - 1 | {92,75,71,52,64,83} | {AAAAAAAA44066,AAAAAA1059,AAAAAAAAAAA176,AAAAAAA48038} - 2 | {3,6} | {AAAAAA98232,AAAAAAAA79710,AAAAAAAAAAAAAAAAA69675,AAAAAAAAAAAAAAAA55798,AAAAAAAAA12793} - 3 | {37,64,95,43,3,41,13,30,11,43} | {AAAAAAAAAA48845,AAAAA75968,AAAAA95309,AAA54451,AAAAAAAAAA22292,AAAAAAA99836,A96617,AA17009,AAAAAAAAAAAAAA95246} - 4 | {71,39,99,55,33,75,45} | {AAAAAAAAA53663,AAAAAAAAAAAAAAA67062,AAAAAAAAAA64777,AAA99043,AAAAAAAAAAAAAAAAAAA91804,39557} - 5 | {50,42,77,50,4} | {AAAAAAAAAAAAAAAAA26540,AAAAAAA79710,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA176,AAAAA95309,AAAAAAAAAAA46154,AAAAAA66777,AAAAAAAAA27249,AAAAAAAAAA64777,AAAAAAAAAAAAAAAAAAA70104} - 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} - 7 | {12,51,88,64,8} | {AAAAAAAAAAAAAAAAAA12591,AAAAAAAAAAAAAAAAA50407,AAAAAAAAAAAA67946} - 8 | {60,84} | {AAAAAAA81898,AAAAAA1059,AAAAAAAAAAAA81511,AAAAA961,AAAAAAAAAAAAAAAA31334,AAAAA64741,AA6416,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAAAA50407} - 9 | {56,52,35,27,80,44,81,22} | {AAAAAAAAAAAAAAA73034,AAAAAAAAAAAAA7929,AAAAAAA66161,AA88409,39557,A27153,AAAAAAAA9523,AAAAAAAAAAA99000} - 10 | {71,5,45} | {AAAAAAAAAAA21658,AAAAAAAAAAAA21089,AAA54451,AAAAAAAAAAAAAAAAAA54141,AAAAAAAAAAAAAA28620,AAAAAAAAAAA21658,AAAAAAAAAAA74076,AAAAAAAAA27249} - 11 | {41,86,74,48,22,74,47,50} | {AAAAAAAA9523,AAAAAAAAAAAA37562,AAAAAAAAAAAAAAAA14047,AAAAAAAAAAA46154,AAAA41702,AAAAAAAAAAAAAAAAA764,AAAAA62737,39557} - 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} - 13 | {3,52,34,23} | {AAAAAA98232,AAAA49534,AAAAAAAAAAA21658} - 14 | {78,57,19} | {AAAA8857,AAAAAAAAAAAAAAA73034,AAAAAAAA81587,AAAAAAAAAAAAAAA68526,AAAAA75968,AAAAAAAAAAAAAA65909,AAAAAAAAA10012,AAAAAAAAAAAAAA65909} - 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} - 16 | {14,63,85,11} | {AAAAAA66777} - 17 | {7,10,81,85} | {AAAAAA43678,AAAAAAA12144,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAAAAA15356} - 18 | {1} | {AAAAAAAAAAA33576,AAAAA95309,64261,AAA59323,AAAAAAAAAAAAAA95246,55847,AAAAAAAAAAAA67946,AAAAAAAAAAAAAAAAAA64374} - 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} - 20 | {72,89,70,51,54,37,8,49,79} | {AAAAAA58494} - 21 | {2,8,65,10,5,79,43} | {AAAAAAAAAAAAAAAAA88852,AAAAAAAAAAAAAAAAAAA91804,AAAAA64669,AAAAAAAAAAAAAAAA1443,AAAAAAAAAAAAAAAA23657,AAAAA12179,AAAAAAAAAAAAAAAAA88852,AAAAAAAAAAAAAAAA31334,AAAAAAAAAAAAAAAA41303,AAAAAAAAAAAAAAAAAAA85420} - 22 | {11,6,56,62,53,30} | {AAAAAAAA72908} - 23 | {40,90,5,38,72,40,30,10,43,55} | {A6053,AAAAAAAAAAA6119,AA44673,AAAAAAAAAAAAAAAAA764,AA17009,AAAAA17383,AAAAA70514,AAAAA33250,AAAAA95309,AAAAAAAAAAAA37562} - 24 | {94,61,99,35,48} | {AAAAAAAAAAA50956,AAAAAAAAAAA15165,AAAA85070,AAAAAAAAAAAAAAA36627,AAAAA961,AAAAAAAAAA55219} - 25 | {31,1,10,11,27,79,38} | {AAAAAAAAAAAAAAAAAA59334,45449} - 26 | {71,10,9,69,75} | {47735,AAAAAAA21462,AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAAAAA91804,AAAAAAAAA72121,AAAAAAAAAAAAAAAAAAA1205,AAAAA41597,AAAA8857,AAAAAAAAAAAAAAAAAAA15356,AA17009} - 27 | {94} | {AA6416,A6053,AAAAAAA21462,AAAAAAA57334,AAAAAAAAAAAAAAAAAA12591,AA88409,AAAAAAAAAAAAA70254} - 28 | {14,33,6,34,14} | {AAAAAAAAAAAAAAA13198,AAAAAAAA69452,AAAAAAAAAAA82945,AAAAAAA12144,AAAAAAAAA72121,AAAAAAAAAA18601} - 29 | {39,21} | {AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAAAAA38885,AAAA85070,AAAAAAAAAAAAAAAAAAA70104,AAAAA66674,AAAAAAAAAAAAA62007,AAAAAAAA69452,AAAAAAA1242,AAAAAAAAAAAAAAAA1729,AAAA35194} - 30 | {26,81,47,91,34} | {AAAAAAAAAAAAAAAAAAA70104,AAAAAAA80240} - 31 | {80,24,18,21,54} | {AAAAAAAAAAAAAAA13198,AAAAAAAAAAAAAAAAAAA70415,A27153,AAAAAAAAA53663,AAAAAAAAAAAAAAAAA50407,A68938} - 32 | {58,79,82,80,67,75,98,10,41} | {AAAAAAAAAAAAAAAAAA61286,AAA54451,AAAAAAAAAAAAAAAAAAA87527,A96617,51533} - 33 | {74,73} | {A85417,AAAAAAA56483,AAAAA17383,AAAAAAAAAAAAA62159,AAAAAAAAAAAA52814,AAAAAAAAAAAAA85723,AAAAAAAAAAAAAAAAAA55796} - 34 | {70,45} | {AAAAAAAAAAAAAAAAAA71621,AAAAAAAAAAAAAA28620,AAAAAAAAAA55219,AAAAAAAA23648,AAAAAAAAAA22292,AAAAAAA1242} - 35 | {23,40} | {AAAAAAAAAAAA52814,AAAA48949,AAAAAAAAA34727,AAAA8857,AAAAAAAAAAAAAAAAAAA62179,AAAAAAAAAAAAAAA68526,AAAAAAA99836,AAAAAAAA50094,AAAA91194,AAAAAAAAAAAAA73084} - 36 | {79,82,14,52,30,5,79} | {AAAAAAAAA53663,AAAAAAAAAAAAAAAA55798,AAAAAAAAAAAAAAAAAAA89194,AA88409,AAAAAAAAAAAAAAA81326,AAAAAAAAAAAAAAAAA63050,AAAAAAAAAAAAAAAA33598} - 37 | {53,11,81,39,3,78,58,64,74} | {AAAAAAAAAAAAAAAAAAA17075,AAAAAAA66161,AAAAAAAA23648,AAAAAAAAAAAAAA10611} - 38 | {59,5,4,95,28} | {AAAAAAAAAAA82945,A96617,47735,AAAAA12179,AAAAA64669,AAAAAA99807,AA74433,AAAAAAAAAAAAAAAAA59387} - 39 | {82,43,99,16,74} | {AAAAAAAAAAAAAAA67062,AAAAAAA57334,AAAAAAAAAAAAAA65909,A27153,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAA64777,AAAAAAAAAAAA81511,AAAAAAAAAAAAAA65909,AAAAAAAAAAAAAA28620} - 40 | {34} | {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623} - 41 | {19,26,63,12,93,73,27,94} | {AAAAAAA79710,AAAAAAAAAA55219,AAAA41702,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAAA71621,AAAAAAAAAAAAAAAAA63050,AAAAAAA99836,AAAAAAAAAAAAAA8666} - 42 | {15,76,82,75,8,91} | {AAAAAAAAAAA176,AAAAAA38063,45449,AAAAAA54032,AAAAAAA81898,AA6416,AAAAAAAAAAAAAAAAAAA62179,45449,AAAAA60038,AAAAAAAA81587} - 43 | {39,87,91,97,79,28} | {AAAAAAAAAAA74076,A96617,AAAAAAAAAAAAAAAAAAA89194,AAAAAAAAAAAAAAAAAA55796,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAA67946} - 44 | {40,58,68,29,54} | {AAAAAAA81898,AAAAAA66777,AAAAAA98232} - 45 | {99,45} | {AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611} - 46 | {53,24} | {AAAAAAAAAAA53908,AAAAAA54032,AAAAA17383,AAAA48949,AAAAAAAAAA18601,AAAAA64669,45449,AAAAAAAAAAA98051,AAAAAAAAAAAAAAAAAA71621} - 47 | {98,23,64,12,75,61} | {AAA59323,AAAAA95309,AAAAAAAAAAAAAAAA31334,AAAAAAAAA27249,AAAAA17383,AAAAAAAAAAAA37562,AAAAAA1059,A84822,55847,AAAAA70466} - 48 | {76,14} | {AAAAAAAAAAAAA59671,AAAAAAAAAAAAAAAAAAA91804,AAAAAA66777,AAAAAAAAAAAAAAAAAAA89194,AAAAAAAAAAAAAAA36627,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAA73084,AAAAAAA79710,AAAAAAAAAAAAAAA40402,AAAAAAAAAAAAAAAAAAA65037} - 49 | {56,5,54,37,49} | {AA21643,AAAAAAAAAAA92631,AAAAAAAA81587} - 50 | {20,12,37,64,93} | {AAAAAAAAAA5483,AAAAAAAAAAAAAAAAAAA1205,AA6416,AAAAAAAAAAAAAAAAA63050,AAAAAAAAAAAAAAAAAA47955} - 51 | {47} | {AAAAAAAAAAAAAA96505,AAAAAAAAAAAAAAAAAA36842,AAAAA95309,AAAAAAAA81587,AA6416,AAAA91194,AAAAAA58494,AAAAAA1059,AAAAAAAA69452} - 52 | {89,0} | {AAAAAAAAAAAAAAAAAA47955,AAAAAAA48038,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAAAAA73084,AAAAA70466,AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA46154,AA66862} - 53 | {38,17} | {AAAAAAAAAAA21658} - 54 | {70,47} | {AAAAAAAAAAAAAAAAAA54141,AAAAA40681,AAAAAAA48038,AAAAAAAAAAAAAAAA29150,AAAAA41597,AAAAAAAAAAAAAAAAAA59334,AA15322} - 55 | {47,79,47,64,72,25,71,24,93} | {AAAAAAAAAAAAAAAAAA55796,AAAAA62737} - 56 | {33,7,60,54,93,90,77,85,39} | {AAAAAAAAAAAAAAAAAA32918,AA42406} - 57 | {23,45,10,42,36,21,9,96} | {AAAAAAAAAAAAAAAAAAA70415} - 58 | {92} | {AAAAAAAAAAAAAAAA98414,AAAAAAAA23648,AAAAAAAAAAAAAAAAAA55796,AA25381,AAAAAAAAAAA6119} - 59 | {9,69,46,77} | {39557,AAAAAAA89932,AAAAAAAAAAAAAAAAA43052,AAAAAAAAAAAAAAAAA26540,AAA20874,AA6416,AAAAAAAAAAAAAAAAAA47955} - 60 | {62,2,59,38,89} | {AAAAAAA89932,AAAAAAAAAAAAAAAAAAA15356,AA99927,AA17009,AAAAAAAAAAAAAAA35875} - 61 | {72,2,44,95,54,54,13} | {AAAAAAAAAAAAAAAAAAA91804} - 62 | {83,72,29,73} | {AAAAAAAAAAAAA15097,AAAA8857,AAAAAAAAAAAA35809,AAAAAAAAAAAA52814,AAAAAAAAAAAAAAAAAAA38885,AAAAAAAAAAAAAAAAAA24183,AAAAAA43678,A96617} - 63 | {11,4,61,87} | {AAAAAAAAA27249,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAA13198,AAA20874,39557,51533,AAAAAAAAAAA53908,AAAAAAAAAAAAAA96505,AAAAAAAA78938} - 64 | {26,19,34,24,81,78} | {A96617,AAAAAAAAAAAAAAAAAAA70104,A68938,AAAAAAAAAAA53908,AAAAAAAAAAAAAAA453,AA17009,AAAAAAA80240} - 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} - 66 | {31,23,70,52,4,33,48,25} | {AAAAAAAAAAAAAAAAA69675,AAAAAAAA50094,AAAAAAAAAAA92631,AAAA35194,39557,AAAAAAA99836} - 67 | {31,94,7,10} | {AAAAAA38063,A96617,AAAA35194,AAAAAAAAAAAA67946} - 68 | {90,43,38} | {AA75092,AAAAAAAAAAAAAAAAA69675,AAAAAAAAAAA92631,AAAAAAAAA10012,AAAAAAAAAAAAA7929,AA21643} - 69 | {67,35,99,85,72,86,44} | {AAAAAAAAAAAAAAAAAAA1205,AAAAAAAA50094,AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAAAAAAA47955} - 70 | {56,70,83} | {AAAA41702,AAAAAAAAAAA82945,AA21643,AAAAAAAAAAA99000,A27153,AA25381,AAAAAAAAAAAAAA96505,AAAAAAA1242} - 71 | {74,26} | {AAAAAAAAAAA50956,AA74433,AAAAAAA21462,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAA36627,AAAAAAAAAAAAA70254,AAAAAAAAAA43419,39557} - 72 | {22,1,16,78,20,91,83} | {47735,AAAAAAA56483,AAAAAAAAAAAAA93788,AA42406,AAAAAAAAAAAAA73084,AAAAAAAA72908,AAAAAAAAAAAAAAAAAA61286,AAAAA66674,AAAAAAAAAAAAAAAAA50407} - 73 | {88,25,96,78,65,15,29,19} | {AAA54451,AAAAAAAAA27249,AAAAAAA9228,AAAAAAAAAAAAAAA67062,AAAAAAAAAAAAAAAAAAA70415,AAAAA17383,AAAAAAAAAAAAAAAA33598} - 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} - 75 | {12,96,83,24,71,89,55} | {AAAA48949,AAAAAAAA29716,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAAA67946,AAAAAAAAAAAAAAAA29150,AAA28075,AAAAAAAAAAAAAAAAA43052} - 76 | {92,55,10,7} | {AAAAAAAAAAAAAAA67062} - 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} - 78 | {55,89,44,84,34} | {AAAAAAAAAAA6119,AAAAAAAAAAAAAA8666,AA99927,AA42406,AAAAAAA81898,AAAAAAA9228,AAAAAAAAAAA92631,AA21643,AAAAAAAAAAAAAA28620} - 79 | {45} | {AAAAAAAAAA646,AAAAAAAAAAAAAAAAAAA70415,AAAAAA43678,AAAAAAAA72908} - 80 | {74,89,44,80,0} | {AAAA35194,AAAAAAAA79710,AAA20874,AAAAAAAAAAAAAAAAAAA70104,AAAAAAAAAAAAA73084,AAAAAAA57334,AAAAAAA9228,AAAAAAAAAAAAA62007} - 81 | {63,77,54,48,61,53,97} | {AAAAAAAAAAAAAAA81326,AAAAAAAAAA22292,AA25381,AAAAAAAAAAA74076,AAAAAAA81898,AAAAAAAAA72121} - 82 | {34,60,4,79,78,16,86,89,42,50} | {AAAAA40681,AAAAAAAAAAAAAAAAAA12591,AAAAAAA80240,AAAAAAAAAAAAAAAA55798,AAAAAAAAAAAAAAAAAAA70104} - 83 | {14,10} | {AAAAAAAAAA22292,AAAAAAAAAAAAA70254,AAAAAAAAAAA6119} - 84 | {11,83,35,13,96,94} | {AAAAA95309,AAAAAAAAAAAAAAAAAA32918,AAAAAAAAAAAAAAAAAA24183} - 85 | {39,60} | {AAAAAAAAAAAAAAAA55798,AAAAAAAAAA22292,AAAAAAA66161,AAAAAAA21462,AAAAAAAAAAAAAAAAAA12591,55847,AAAAAA98232,AAAAAAAAAAA46154} - 86 | {33,81,72,74,45,36,82} | {AAAAAAAA81587,AAAAAAAAAAAAAA96505,45449,AAAA80176} - 87 | {57,27,50,12,97,68} | {AAAAAAAAAAAAAAAAA26540,AAAAAAAAA10012,AAAAAAAAAAAA35809,AAAAAAAAAAAAAAAA29150,AAAAAAAAAAA82945,AAAAAA66777,31228,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAA96505} - 88 | {41,90,77,24,6,24} | {AAAA35194,AAAA35194,AAAAAAA80240,AAAAAAAAAAA46154,AAAAAA58494,AAAAAAAAAAAAAAAAAAA17075,AAAAAAAAAAAAAAAAAA59334,AAAAAAAAAAAAAAAAAAA91804,AA74433} - 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} - 90 | {88,75} | {AAAAA60038,AAAAAAAA23648,AAAAAAAAAAA99000,AAAA41702,AAAAAAAAAAAAA22860,AAAAAAAAAAAAAAA68526} - 91 | {78} | {AAAAAAAAAAAAA62007,AAA99043} - 92 | {85,63,49,45} | {AAAAAAA89932,AAAAAAAAAAAAA22860,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAAA21089} - 93 | {11} | {AAAAAAAAAAA176,AAAAAAAAAAAAAA8666,AAAAAAAAAAAAAAA453,AAAAAAAAAAAAA85723,A68938,AAAAAAAAAAAAA9821,AAAAAAA48038,AAAAAAAAAAAAAAAAA59387,AA99927,AAAAA17383} - 94 | {98,9,85,62,88,91,60,61,38,86} | {AAAAAAAA81587,AAAAA17383,AAAAAAAA81587} - 95 | {47,77} | {AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA74076,AAAAAAAAAA18107,AAAAA40681,AAAAAAAAAAAAAAA35875,AAAAA60038,AAAAAAA56483} - 96 | {23,97,43} | {AAAAAAAAAA646,A87088} - 97 | {54,2,86,65} | {47735,AAAAAAA99836,AAAAAAAAAAAAAAAAA6897,AAAAAAAAAAAAAAAA29150,AAAAAAA80240,AAAAAAAAAAAAAAAA98414,AAAAAAA56483,AAAAAAAAAAAAAAAA29150,AAAAAAA39692,AA21643} - 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} - 99 | {37,86} | {AAAAAAAAAAAAAAAAAA32918,AAAAA70514,AAAAAAAAA10012,AAAAAAAAAAAAAAAAA59387,AAAAAAAAAA64777,AAAAAAAAAAAAAAAAAAA15356} - 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} - 101 | {} | {} - 102 | {NULL} | {NULL} -(102 rows) - -SELECT * FROM array_op_test WHERE t && '{}' ORDER BY seqno; - seqno | i | t --------+---+--- -(0 rows) - -SELECT * FROM array_op_test WHERE t <@ '{}' ORDER BY seqno; - seqno | i | t --------+----+---- - 101 | {} | {} -(1 row) - --- array casts -SELECT ARRAY[1,2,3]::text[]::int[]::float8[] AS "{1,2,3}"; - {1,2,3} ---------- - {1,2,3} -(1 row) - -SELECT pg_typeof(ARRAY[1,2,3]::text[]::int[]::float8[]) AS "double precision[]"; - double precision[] --------------------- - double precision[] -(1 row) - -SELECT ARRAY[['a','bc'],['def','hijk']]::text[]::varchar[] AS "{{a,bc},{def,hijk}}"; - {{a,bc},{def,hijk}} ---------------------- - {{a,bc},{def,hijk}} -(1 row) - -SELECT pg_typeof(ARRAY[['a','bc'],['def','hijk']]::text[]::varchar[]) AS "character varying[]"; - character varying[] ---------------------- - character varying[] -(1 row) - -SELECT CAST(ARRAY[[[[[['a','bb','ccc']]]]]] as text[]) as "{{{{{{a,bb,ccc}}}}}}"; - {{{{{{a,bb,ccc}}}}}} ----------------------- - {{{{{{a,bb,ccc}}}}}} -(1 row) - -SELECT NULL::text[]::int[] AS "NULL"; - NULL ------- - -(1 row) - --- scalar op any/all (array) -select 33 = any ('{1,2,3}'); - ?column? ----------- - f -(1 row) - -select 33 = any ('{1,2,33}'); - ?column? ----------- - t -(1 row) - -select 33 = all ('{1,2,33}'); - ?column? ----------- - f -(1 row) - -select 33 >= all ('{1,2,33}'); - ?column? ----------- - t -(1 row) - --- boundary cases -select null::int >= all ('{1,2,33}'); - ?column? ----------- - -(1 row) - -select null::int >= all ('{}'); - ?column? ----------- - t -(1 row) - -select null::int >= any ('{}'); - ?column? ----------- - f -(1 row) - --- cross-datatype -select 33.4 = any (array[1,2,3]); - ?column? ----------- - f -(1 row) - -select 33.4 > all (array[1,2,3]); - ?column? ----------- - t -(1 row) - --- errors -select 33 * any ('{1,2,3}'); -ERROR: op ANY/ALL (array) requires operator to yield boolean -LINE 1: select 33 * any ('{1,2,3}'); - ^ -select 33 * any (44); -ERROR: op ANY/ALL (array) requires array on right side -LINE 1: select 33 * any (44); - ^ --- nulls -select 33 = any (null::int[]); - ?column? ----------- - -(1 row) - -select null::int = any ('{1,2,3}'); - ?column? ----------- - -(1 row) - -select 33 = any ('{1,null,3}'); - ?column? ----------- - -(1 row) - -select 33 = any ('{1,null,33}'); - ?column? ----------- - t -(1 row) - -select 33 = all (null::int[]); - ?column? ----------- - -(1 row) - -select null::int = all ('{1,2,3}'); - ?column? ----------- - -(1 row) - -select 33 = all ('{1,null,3}'); - ?column? ----------- - f -(1 row) - -select 33 = all ('{33,null,33}'); - ?column? ----------- - -(1 row) - --- nulls later in the bitmap -SELECT -1 != ALL(ARRAY(SELECT NULLIF(g.i, 900) FROM generate_series(1,1000) g(i))); - ?column? ----------- - -(1 row) - --- test indexes on arrays -create temp table arr_tbl (f1 int[] unique); -insert into arr_tbl values ('{1,2,3}'); -insert into arr_tbl values ('{1,2}'); --- failure expected: -insert into arr_tbl values ('{1,2,3}'); -ERROR: duplicate key value violates unique constraint "arr_tbl_f1_key" -DETAIL: Key (f1)=({1,2,3}) already exists. -insert into arr_tbl values ('{2,3,4}'); -insert into arr_tbl values ('{1,5,3}'); -insert into arr_tbl values ('{1,2,10}'); -set enable_seqscan to off; -set enable_bitmapscan to off; -select * from arr_tbl where f1 > '{1,2,3}' and f1 <= '{1,5,3}'; - f1 ----------- - {1,2,10} - {1,5,3} -(2 rows) - -select * from arr_tbl where f1 >= '{1,2,3}' and f1 < '{1,5,3}'; - f1 ----------- - {1,2,3} - {1,2,10} -(2 rows) - --- test ON CONFLICT DO UPDATE with arrays -create temp table arr_pk_tbl (pk int4 primary key, f1 int[]); -insert into arr_pk_tbl values (1, '{1,2,3}'); -insert into arr_pk_tbl values (1, '{3,4,5}') on conflict (pk) - do update set f1[1] = excluded.f1[1], f1[3] = excluded.f1[3] - returning pk, f1; - pk | f1 -----+--------- - 1 | {3,2,5} -(1 row) - -insert into arr_pk_tbl(pk, f1[1:2]) values (1, '{6,7,8}') on conflict (pk) - do update set f1[1] = excluded.f1[1], - f1[2] = excluded.f1[2], - f1[3] = excluded.f1[3] - returning pk, f1; - pk | f1 -----+------------ - 1 | {6,7,NULL} -(1 row) - --- note: if above selects don't produce the expected tuple order, --- then you didn't get an indexscan plan, and something is busted. -reset enable_seqscan; -reset enable_bitmapscan; --- test subscript overflow detection --- The normal error message includes a platform-dependent limit, --- so suppress it to avoid needing multiple expected-files. -\set VERBOSITY sqlstate -insert into arr_pk_tbl values(10, '[-2147483648:-2147483647]={1,2}'); -update arr_pk_tbl set f1[2147483647] = 42 where pk = 10; -ERROR: 54000 -update arr_pk_tbl set f1[2147483646:2147483647] = array[4,2] where pk = 10; -ERROR: 54000 --- also exercise the expanded-array case -do $$ declare a int[]; -begin - a := '[-2147483648:-2147483647]={1,2}'::int[]; - a[2147483647] := 42; -end $$; -ERROR: 54000 -\set VERBOSITY default --- test [not] (like|ilike) (any|all) (...) -select 'foo' like any (array['%a', '%o']); -- t - ?column? ----------- - t -(1 row) - -select 'foo' like any (array['%a', '%b']); -- f - ?column? ----------- - f -(1 row) - -select 'foo' like all (array['f%', '%o']); -- t - ?column? ----------- - t -(1 row) - -select 'foo' like all (array['f%', '%b']); -- f - ?column? ----------- - f -(1 row) - -select 'foo' not like any (array['%a', '%b']); -- t - ?column? ----------- - t -(1 row) - -select 'foo' not like all (array['%a', '%o']); -- f - ?column? ----------- - f -(1 row) - -select 'foo' ilike any (array['%A', '%O']); -- t - ?column? ----------- - t -(1 row) - -select 'foo' ilike all (array['F%', '%O']); -- t - ?column? ----------- - t -(1 row) - --- --- General array parser tests --- --- none of the following should be accepted -select '{{1,{2}},{2,3}}'::text[]; -ERROR: malformed array literal: "{{1,{2}},{2,3}}" -LINE 1: select '{{1,{2}},{2,3}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select E'{{1,2},\\{2,3}}'::text[]; -ERROR: malformed array literal: "{{1,2},\{2,3}}" -LINE 1: select E'{{1,2},\\{2,3}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '{"a"b}'::text[]; -ERROR: malformed array literal: "{"a"b}" -LINE 1: select '{"a"b}'::text[]; - ^ -DETAIL: Incorrectly quoted array element. -select '{a"b"}'::text[]; -ERROR: malformed array literal: "{a"b"}" -LINE 1: select '{a"b"}'::text[]; - ^ -DETAIL: Incorrectly quoted array element. -select '{"a""b"}'::text[]; -ERROR: malformed array literal: "{"a""b"}" -LINE 1: select '{"a""b"}'::text[]; - ^ -DETAIL: Incorrectly quoted array element. -select '{{"1 2" x},{3}}'::text[]; -ERROR: malformed array literal: "{{"1 2" x},{3}}" -LINE 1: select '{{"1 2" x},{3}}'::text[]; - ^ -DETAIL: Incorrectly quoted array element. -select '{{"1 2"} x,{3}}'::text[]; -ERROR: malformed array literal: "{{"1 2"} x,{3}}" -LINE 1: select '{{"1 2"} x,{3}}'::text[]; - ^ -DETAIL: Unexpected array element. -select '{}}'::text[]; -ERROR: malformed array literal: "{}}" -LINE 1: select '{}}'::text[]; - ^ -DETAIL: Junk after closing right brace. -select '{ }}'::text[]; -ERROR: malformed array literal: "{ }}" -LINE 1: select '{ }}'::text[]; - ^ -DETAIL: Junk after closing right brace. -select '}{'::text[]; -ERROR: malformed array literal: "}{" -LINE 1: select '}{'::text[]; - ^ -DETAIL: Array value must start with "{" or dimension information. -select '{foo{}}'::text[]; -ERROR: malformed array literal: "{foo{}}" -LINE 1: select '{foo{}}'::text[]; - ^ -DETAIL: Unexpected "{" character. -select '{"foo"{}}'::text[]; -ERROR: malformed array literal: "{"foo"{}}" -LINE 1: select '{"foo"{}}'::text[]; - ^ -DETAIL: Unexpected "{" character. -select '{foo,,bar}'::text[]; -ERROR: malformed array literal: "{foo,,bar}" -LINE 1: select '{foo,,bar}'::text[]; - ^ -DETAIL: Unexpected "," character. -select '{{1},{{2}}}'::text[]; -ERROR: malformed array literal: "{{1},{{2}}}" -LINE 1: select '{{1},{{2}}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '{{{1}},{2}}'::text[]; -ERROR: malformed array literal: "{{{1}},{2}}" -LINE 1: select '{{{1}},{2}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '{{},{{}}}'::text[]; -ERROR: malformed array literal: "{{},{{}}}" -LINE 1: select '{{},{{}}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '{{{}},{}}'::text[]; -ERROR: malformed array literal: "{{{}},{}}" -LINE 1: select '{{{}},{}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '{{1},{}}'::text[]; -ERROR: malformed array literal: "{{1},{}}" -LINE 1: select '{{1},{}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '{{},{1}}'::text[]; -ERROR: malformed array literal: "{{},{1}}" -LINE 1: select '{{},{1}}'::text[]; - ^ -DETAIL: Multidimensional arrays must have sub-arrays with matching dimensions. -select '[1:0]={}'::int[]; -ERROR: upper bound cannot be less than lower bound -LINE 1: select '[1:0]={}'::int[]; - ^ -select '[2147483646:2147483647]={1,2}'::int[]; -ERROR: array upper bound is too large: 2147483647 -LINE 1: select '[2147483646:2147483647]={1,2}'::int[]; - ^ -select '[1:-1]={}'::int[]; -ERROR: upper bound cannot be less than lower bound -LINE 1: select '[1:-1]={}'::int[]; - ^ -select '[2]={1}'::int[]; -ERROR: malformed array literal: "[2]={1}" -LINE 1: select '[2]={1}'::int[]; - ^ -DETAIL: Specified array dimensions do not match array contents. -select '[1:]={1}'::int[]; -ERROR: malformed array literal: "[1:]={1}" -LINE 1: select '[1:]={1}'::int[]; - ^ -DETAIL: Missing array dimension value. -select '[:1]={1}'::int[]; -ERROR: malformed array literal: "[:1]={1}" -LINE 1: select '[:1]={1}'::int[]; - ^ -DETAIL: "[" must introduce explicitly-specified array dimensions. -select array[]; -ERROR: cannot determine type of empty array -LINE 1: select array[]; - ^ -HINT: Explicitly cast to the desired type, for example ARRAY[]::integer[]. -select '{{1,},{1},}'::text[]; -ERROR: malformed array literal: "{{1,},{1},}" -LINE 1: select '{{1,},{1},}'::text[]; - ^ -DETAIL: Unexpected "}" character. -select '{{1,},{1}}'::text[]; -ERROR: malformed array literal: "{{1,},{1}}" -LINE 1: select '{{1,},{1}}'::text[]; - ^ -DETAIL: Unexpected "}" character. -select '{{1,}}'::text[]; -ERROR: malformed array literal: "{{1,}}" -LINE 1: select '{{1,}}'::text[]; - ^ -DETAIL: Unexpected "}" character. -select '{1,}'::text[]; -ERROR: malformed array literal: "{1,}" -LINE 1: select '{1,}'::text[]; - ^ -DETAIL: Unexpected "}" character. -select '[21474836488:21474836489]={1,2}'::int[]; -ERROR: array bound is out of integer range -LINE 1: select '[21474836488:21474836489]={1,2}'::int[]; - ^ -select '[-2147483649:-2147483648]={1,2}'::int[]; -ERROR: array bound is out of integer range -LINE 1: select '[-2147483649:-2147483648]={1,2}'::int[]; - ^ --- none of the above should be accepted --- all of the following should be accepted -select '{}'::text[]; - text ------- - {} -(1 row) - -select '{{},{}}'::text[]; - text ------- - {} -(1 row) - -select '{{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}}'::text[]; - text ------------------------------------------------ - {{{1,2,3,4},{2,3,4,5}},{{3,4,5,6},{4,5,6,7}}} -(1 row) - -select '{null,n\ull,"null"}'::text[]; - text ----------------------- - {NULL,"null","null"} -(1 row) - -select '{ ab\c , "ab\"c" }'::text[]; - text ---------------- - {abc,"ab\"c"} -(1 row) - -select '{0 second ,0 second}'::interval[]; - interval ---------------- - {"@ 0","@ 0"} -(1 row) - -select '{ { "," } , { 3 } }'::text[]; - text -------------- - {{","},{3}} -(1 row) - -select ' { { " 0 second " , 0 second } }'::text[]; - text -------------------------------- - {{" 0 second ","0 second"}} -(1 row) - -select '{ - 0 second, - @ 1 hour @ 42 minutes @ 20 seconds - }'::interval[]; - interval ------------------------------------- - {"@ 0","@ 1 hour 42 mins 20 secs"} -(1 row) - -select array[]::text[]; - array -------- - {} -(1 row) - -select '[2]={1,7}'::int[]; - int4 -------- - {1,7} -(1 row) - -select '[0:1]={1.1,2.2}'::float8[]; - float8 ------------------ - [0:1]={1.1,2.2} -(1 row) - -select '[2147483646:2147483646]={1}'::int[]; - int4 ------------------------------ - [2147483646:2147483646]={1} -(1 row) - -select '[-2147483648:-2147483647]={1,2}'::int[]; - int4 ---------------------------------- - [-2147483648:-2147483647]={1,2} -(1 row) - --- all of the above should be accepted --- tests for array aggregates -CREATE TEMP TABLE arraggtest ( f1 INT[], f2 TEXT[][], f3 FLOAT[]); -INSERT INTO arraggtest (f1, f2, f3) VALUES -('{1,2,3,4}','{{grey,red},{blue,blue}}','{1.6, 0.0}'); -INSERT INTO arraggtest (f1, f2, f3) VALUES -('{1,2,3}','{{grey,red},{grey,blue}}','{1.6}'); -SELECT max(f1), min(f1), max(f2), min(f2), max(f3), min(f3) FROM arraggtest; - max | min | max | min | max | min ------------+---------+--------------------------+--------------------------+---------+------- - {1,2,3,4} | {1,2,3} | {{grey,red},{grey,blue}} | {{grey,red},{blue,blue}} | {1.6,0} | {1.6} -(1 row) - -INSERT INTO arraggtest (f1, f2, f3) VALUES -('{3,3,2,4,5,6}','{{white,yellow},{pink,orange}}','{2.1,3.3,1.8,1.7,1.6}'); -SELECT max(f1), min(f1), max(f2), min(f2), max(f3), min(f3) FROM arraggtest; - max | min | max | min | max | min ----------------+---------+--------------------------------+--------------------------+-----------------------+------- - {3,3,2,4,5,6} | {1,2,3} | {{white,yellow},{pink,orange}} | {{grey,red},{blue,blue}} | {2.1,3.3,1.8,1.7,1.6} | {1.6} -(1 row) - -INSERT INTO arraggtest (f1, f2, f3) VALUES -('{2}','{{black,red},{green,orange}}','{1.6,2.2,2.6,0.4}'); -SELECT max(f1), min(f1), max(f2), min(f2), max(f3), min(f3) FROM arraggtest; - max | min | max | min | max | min ----------------+---------+--------------------------------+------------------------------+-----------------------+------- - {3,3,2,4,5,6} | {1,2,3} | {{white,yellow},{pink,orange}} | {{black,red},{green,orange}} | {2.1,3.3,1.8,1.7,1.6} | {1.6} -(1 row) - -INSERT INTO arraggtest (f1, f2, f3) VALUES -('{4,2,6,7,8,1}','{{red},{black},{purple},{blue},{blue}}',NULL); -SELECT max(f1), min(f1), max(f2), min(f2), max(f3), min(f3) FROM arraggtest; - max | min | max | min | max | min ----------------+---------+--------------------------------+------------------------------+-----------------------+------- - {4,2,6,7,8,1} | {1,2,3} | {{white,yellow},{pink,orange}} | {{black,red},{green,orange}} | {2.1,3.3,1.8,1.7,1.6} | {1.6} -(1 row) - -INSERT INTO arraggtest (f1, f2, f3) VALUES -('{}','{{pink,white,blue,red,grey,orange}}','{2.1,1.87,1.4,2.2}'); -SELECT max(f1), min(f1), max(f2), min(f2), max(f3), min(f3) FROM arraggtest; - max | min | max | min | max | min ----------------+-----+--------------------------------+------------------------------+-----------------------+------- - {4,2,6,7,8,1} | {} | {{white,yellow},{pink,orange}} | {{black,red},{green,orange}} | {2.1,3.3,1.8,1.7,1.6} | {1.6} -(1 row) - --- A few simple tests for arrays of composite types -create type comptype as (f1 int, f2 text); -create table comptable (c1 comptype, c2 comptype[]); --- XXX would like to not have to specify row() construct types here ... -insert into comptable - values (row(1,'foo'), array[row(2,'bar')::comptype, row(3,'baz')::comptype]); --- check that implicitly named array type _comptype isn't a problem -create type _comptype as enum('fooey'); -select * from comptable; - c1 | c2 ----------+----------------------- - (1,foo) | {"(2,bar)","(3,baz)"} -(1 row) - -select c2[2].f2 from comptable; - f2 ------ - baz -(1 row) - -drop type _comptype; -drop table comptable; -drop type comptype; -create or replace function unnest1(anyarray) -returns setof anyelement as $$ -select $1[s] from generate_subscripts($1,1) g(s); -$$ language sql immutable; -create or replace function unnest2(anyarray) -returns setof anyelement as $$ -select $1[s1][s2] from generate_subscripts($1,1) g1(s1), - generate_subscripts($1,2) g2(s2); -$$ language sql immutable; -select * from unnest1(array[1,2,3]); - unnest1 ---------- - 1 - 2 - 3 -(3 rows) - -select * from unnest2(array[[1,2,3],[4,5,6]]); - unnest2 ---------- - 1 - 2 - 3 - 4 - 5 - 6 -(6 rows) - -drop function unnest1(anyarray); -drop function unnest2(anyarray); -select array_fill(null::integer, array[3,3],array[2,2]); - array_fill ------------------------------------------------------------------ - [2:4][2:4]={{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}} -(1 row) - -select array_fill(null::integer, array[3,3]); - array_fill ------------------------------------------------------- - {{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}} -(1 row) - -select array_fill(null::text, array[3,3],array[2,2]); - array_fill ------------------------------------------------------------------ - [2:4][2:4]={{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}} -(1 row) - -select array_fill(null::text, array[3,3]); - array_fill ------------------------------------------------------- - {{NULL,NULL,NULL},{NULL,NULL,NULL},{NULL,NULL,NULL}} -(1 row) - -select array_fill(7, array[3,3],array[2,2]); - array_fill --------------------------------------- - [2:4][2:4]={{7,7,7},{7,7,7},{7,7,7}} -(1 row) - -select array_fill(7, array[3,3]); - array_fill ---------------------------- - {{7,7,7},{7,7,7},{7,7,7}} -(1 row) - -select array_fill('juhu'::text, array[3,3],array[2,2]); - array_fill ------------------------------------------------------------------ - [2:4][2:4]={{juhu,juhu,juhu},{juhu,juhu,juhu},{juhu,juhu,juhu}} -(1 row) - -select array_fill('juhu'::text, array[3,3]); - array_fill ------------------------------------------------------- - {{juhu,juhu,juhu},{juhu,juhu,juhu},{juhu,juhu,juhu}} -(1 row) - -select a, a = '{}' as is_eq, array_dims(a) - from (select array_fill(42, array[0]) as a) ss; - a | is_eq | array_dims -----+-------+------------ - {} | t | -(1 row) - -select a, a = '{}' as is_eq, array_dims(a) - from (select array_fill(42, '{}') as a) ss; - a | is_eq | array_dims -----+-------+------------ - {} | t | -(1 row) - -select a, a = '{}' as is_eq, array_dims(a) - from (select array_fill(42, '{}', '{}') as a) ss; - a | is_eq | array_dims -----+-------+------------ - {} | t | -(1 row) - --- raise exception -select array_fill(1, null, array[2,2]); -ERROR: dimension array or low bound array cannot be null -select array_fill(1, array[2,2], null); -ERROR: dimension array or low bound array cannot be null -select array_fill(1, array[2,2], '{}'); -ERROR: wrong number of array subscripts -DETAIL: Low bound array has different size than dimensions array. -select array_fill(1, array[3,3], array[1,1,1]); -ERROR: wrong number of array subscripts -DETAIL: Low bound array has different size than dimensions array. -select array_fill(1, array[1,2,null]); -ERROR: dimension values cannot be null -select array_fill(1, array[[1,2],[3,4]]); -ERROR: wrong number of array subscripts -DETAIL: Dimension array must be one dimensional. -select string_to_array('1|2|3', '|'); - string_to_array ------------------ - {1,2,3} -(1 row) - -select string_to_array('1|2|3|', '|'); - string_to_array ------------------ - {1,2,3,""} -(1 row) - -select string_to_array('1||2|3||', '||'); - string_to_array ------------------ - {1,2|3,""} -(1 row) - -select string_to_array('1|2|3', ''); - string_to_array ------------------ - {1|2|3} -(1 row) - -select string_to_array('', '|'); - string_to_array ------------------ - {} -(1 row) - -select string_to_array('1|2|3', NULL); - string_to_array ------------------ - {1,|,2,|,3} -(1 row) - -select string_to_array(NULL, '|') IS NULL; - ?column? ----------- - t -(1 row) - -select string_to_array('abc', ''); - string_to_array ------------------ - {abc} -(1 row) - -select string_to_array('abc', '', 'abc'); - string_to_array ------------------ - {NULL} -(1 row) - -select string_to_array('abc', ','); - string_to_array ------------------ - {abc} -(1 row) - -select string_to_array('abc', ',', 'abc'); - string_to_array ------------------ - {NULL} -(1 row) - -select string_to_array('1,2,3,4,,6', ','); - string_to_array ------------------ - {1,2,3,4,"",6} -(1 row) - -select string_to_array('1,2,3,4,,6', ',', ''); - string_to_array ------------------- - {1,2,3,4,NULL,6} -(1 row) - -select string_to_array('1,2,3,4,*,6', ',', '*'); - string_to_array ------------------- - {1,2,3,4,NULL,6} -(1 row) - -select v, v is null as "is null" from string_to_table('1|2|3', '|') g(v); - v | is null ----+--------- - 1 | f - 2 | f - 3 | f -(3 rows) - -select v, v is null as "is null" from string_to_table('1|2|3|', '|') g(v); - v | is null ----+--------- - 1 | f - 2 | f - 3 | f - | f -(4 rows) - -select v, v is null as "is null" from string_to_table('1||2|3||', '||') g(v); - v | is null ------+--------- - 1 | f - 2|3 | f - | f -(3 rows) - -select v, v is null as "is null" from string_to_table('1|2|3', '') g(v); - v | is null --------+--------- - 1|2|3 | f -(1 row) - -select v, v is null as "is null" from string_to_table('', '|') g(v); - v | is null ----+--------- -(0 rows) - -select v, v is null as "is null" from string_to_table('1|2|3', NULL) g(v); - v | is null ----+--------- - 1 | f - | | f - 2 | f - | | f - 3 | f -(5 rows) - -select v, v is null as "is null" from string_to_table(NULL, '|') g(v); - v | is null ----+--------- -(0 rows) - -select v, v is null as "is null" from string_to_table('abc', '') g(v); - v | is null ------+--------- - abc | f -(1 row) - -select v, v is null as "is null" from string_to_table('abc', '', 'abc') g(v); - v | is null ----+--------- - | t -(1 row) - -select v, v is null as "is null" from string_to_table('abc', ',') g(v); - v | is null ------+--------- - abc | f -(1 row) - -select v, v is null as "is null" from string_to_table('abc', ',', 'abc') g(v); - v | is null ----+--------- - | t -(1 row) - -select v, v is null as "is null" from string_to_table('1,2,3,4,,6', ',') g(v); - v | is null ----+--------- - 1 | f - 2 | f - 3 | f - 4 | f - | f - 6 | f -(6 rows) - -select v, v is null as "is null" from string_to_table('1,2,3,4,,6', ',', '') g(v); - v | is null ----+--------- - 1 | f - 2 | f - 3 | f - 4 | f - | t - 6 | f -(6 rows) - -select v, v is null as "is null" from string_to_table('1,2,3,4,*,6', ',', '*') g(v); - v | is null ----+--------- - 1 | f - 2 | f - 3 | f - 4 | f - | t - 6 | f -(6 rows) - -select array_to_string(NULL::int4[], ',') IS NULL; - ?column? ----------- - t -(1 row) - -select array_to_string('{}'::int4[], ','); - array_to_string ------------------ - -(1 row) - -select array_to_string(array[1,2,3,4,NULL,6], ','); - array_to_string ------------------ - 1,2,3,4,6 -(1 row) - -select array_to_string(array[1,2,3,4,NULL,6], ',', '*'); - array_to_string ------------------ - 1,2,3,4,*,6 -(1 row) - -select array_to_string(array[1,2,3,4,NULL,6], NULL); - array_to_string ------------------ - -(1 row) - -select array_to_string(array[1,2,3,4,NULL,6], ',', NULL); - array_to_string ------------------ - 1,2,3,4,6 -(1 row) - -select array_to_string(string_to_array('1|2|3', '|'), '|'); - array_to_string ------------------ - 1|2|3 -(1 row) - -select array_length(array[1,2,3], 1); - array_length --------------- - 3 -(1 row) - -select array_length(array[[1,2,3], [4,5,6]], 0); - array_length --------------- - -(1 row) - -select array_length(array[[1,2,3], [4,5,6]], 1); - array_length --------------- - 2 -(1 row) - -select array_length(array[[1,2,3], [4,5,6]], 2); - array_length --------------- - 3 -(1 row) - -select array_length(array[[1,2,3], [4,5,6]], 3); - array_length --------------- - -(1 row) - -select cardinality(NULL::int[]); - cardinality -------------- - -(1 row) - -select cardinality('{}'::int[]); - cardinality -------------- - 0 -(1 row) - -select cardinality(array[1,2,3]); - cardinality -------------- - 3 -(1 row) - -select cardinality('[2:4]={5,6,7}'::int[]); - cardinality -------------- - 3 -(1 row) - -select cardinality('{{1,2}}'::int[]); - cardinality -------------- - 2 -(1 row) - -select cardinality('{{1,2},{3,4},{5,6}}'::int[]); - cardinality -------------- - 6 -(1 row) - -select cardinality('{{{1,9},{5,6}},{{2,3},{3,4}}}'::int[]); - cardinality -------------- - 8 -(1 row) - --- array_agg(anynonarray) -select array_agg(unique1) from (select unique1 from tenk1 where unique1 < 15 order by unique1) ss; - array_agg --------------------------------------- - {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14} -(1 row) - -select array_agg(ten) from (select ten from tenk1 where unique1 < 15 order by unique1) ss; - array_agg ---------------------------------- - {0,1,2,3,4,5,6,7,8,9,0,1,2,3,4} -(1 row) - -select array_agg(nullif(ten, 4)) from (select ten from tenk1 where unique1 < 15 order by unique1) ss; - array_agg ---------------------------------------- - {0,1,2,3,NULL,5,6,7,8,9,0,1,2,3,NULL} -(1 row) - -select array_agg(unique1) from tenk1 where unique1 < -15; - array_agg ------------ - -(1 row) - --- array_agg(anyarray) -select array_agg(ar) - from (values ('{1,2}'::int[]), ('{3,4}'::int[])) v(ar); - array_agg ---------------- - {{1,2},{3,4}} -(1 row) - -select array_agg(distinct ar order by ar desc) - from (select array[i / 2] from generate_series(1,10) a(i)) b(ar); - array_agg ---------------------------- - {{5},{4},{3},{2},{1},{0}} -(1 row) - -select array_agg(ar) - from (select array_agg(array[i, i+1, i-1]) - from generate_series(1,2) a(i)) b(ar); - array_agg ---------------------- - {{{1,2,0},{2,3,1}}} -(1 row) - -select array_agg(array[i+1.2, i+1.3, i+1.4]) from generate_series(1,3) g(i); - array_agg ---------------------------------------------- - {{2.2,2.3,2.4},{3.2,3.3,3.4},{4.2,4.3,4.4}} -(1 row) - -select array_agg(array['Hello', i::text]) from generate_series(9,11) g(i); - array_agg ------------------------------------ - {{Hello,9},{Hello,10},{Hello,11}} -(1 row) - -select array_agg(array[i, nullif(i, 3), i+1]) from generate_series(1,4) g(i); - array_agg --------------------------------------- - {{1,1,2},{2,2,3},{3,NULL,4},{4,4,5}} -(1 row) - --- errors -select array_agg('{}'::int[]) from generate_series(1,2); -ERROR: cannot accumulate empty arrays -select array_agg(null::int[]) from generate_series(1,2); -ERROR: cannot accumulate null arrays -select array_agg(ar) - from (values ('{1,2}'::int[]), ('{3}'::int[])) v(ar); -ERROR: cannot accumulate arrays of different dimensionality -select unnest(array[1,2,3]); - unnest --------- - 1 - 2 - 3 -(3 rows) - -select * from unnest(array[1,2,3]); - unnest --------- - 1 - 2 - 3 -(3 rows) - -select unnest(array[1,2,3,4.5]::float8[]); - unnest --------- - 1 - 2 - 3 - 4.5 -(4 rows) - -select unnest(array[1,2,3,4.5]::numeric[]); - unnest --------- - 1 - 2 - 3 - 4.5 -(4 rows) - -select unnest(array[1,2,3,null,4,null,null,5,6]); - unnest --------- - 1 - 2 - 3 - - 4 - - - 5 - 6 -(9 rows) - -select unnest(array[1,2,3,null,4,null,null,5,6]::text[]); - unnest --------- - 1 - 2 - 3 - - 4 - - - 5 - 6 -(9 rows) - -select abs(unnest(array[1,2,null,-3])); - abs ------ - 1 - 2 - - 3 -(4 rows) - -select array_remove(array[1,2,2,3], 2); - array_remove --------------- - {1,3} -(1 row) - -select array_remove(array[1,2,2,3], 5); - array_remove --------------- - {1,2,2,3} -(1 row) - -select array_remove(array[1,NULL,NULL,3], NULL); - array_remove --------------- - {1,3} -(1 row) - -select array_remove(array['A','CC','D','C','RR'], 'RR'); - array_remove --------------- - {A,CC,D,C} -(1 row) - -select array_remove(array[1.0, 2.1, 3.3], 1); - array_remove --------------- - {2.1,3.3} -(1 row) - -select array_remove('{{1,2,2},{1,4,3}}', 2); -- not allowed -ERROR: removing elements from multidimensional arrays is not supported -select array_remove(array['X','X','X'], 'X') = '{}'; - ?column? ----------- - t -(1 row) - -select array_replace(array[1,2,5,4],5,3); - array_replace ---------------- - {1,2,3,4} -(1 row) - -select array_replace(array[1,2,5,4],5,NULL); - array_replace ---------------- - {1,2,NULL,4} -(1 row) - -select array_replace(array[1,2,NULL,4,NULL],NULL,5); - array_replace ---------------- - {1,2,5,4,5} -(1 row) - -select array_replace(array['A','B','DD','B'],'B','CC'); - array_replace ---------------- - {A,CC,DD,CC} -(1 row) - -select array_replace(array[1,NULL,3],NULL,NULL); - array_replace ---------------- - {1,NULL,3} -(1 row) - -select array_replace(array['AB',NULL,'CDE'],NULL,'12'); - array_replace ---------------- - {AB,12,CDE} -(1 row) - --- array(select array-value ...) -select array(select array[i,i/2] from generate_series(1,5) i); - array ---------------------------------- - {{1,0},{2,1},{3,1},{4,2},{5,2}} -(1 row) - -select array(select array['Hello', i::text] from generate_series(9,11) i); - array ------------------------------------ - {{Hello,9},{Hello,10},{Hello,11}} -(1 row) - --- Insert/update on a column that is array of composite -create temp table t1 (f1 int8_tbl[]); -insert into t1 (f1[5].q1) values(42); -select * from t1; - f1 ------------------ - [5:5]={"(42,)"} -(1 row) - -update t1 set f1[5].q2 = 43; -select * from t1; - f1 -------------------- - [5:5]={"(42,43)"} -(1 row) - --- Check that arrays of composites are safely detoasted when needed -create temp table src (f1 text); -insert into src - select string_agg(random()::text,'') from generate_series(1,10000); -create type textandtext as (c1 text, c2 text); -create temp table dest (f1 textandtext[]); -insert into dest select array[row(f1,f1)::textandtext] from src; -select length(fipshash((f1[1]).c2)) from dest; - length --------- - 32 -(1 row) - -delete from src; -select length(fipshash((f1[1]).c2)) from dest; - length --------- - 32 -(1 row) - -truncate table src; -drop table src; -select length(fipshash((f1[1]).c2)) from dest; - length --------- - 32 -(1 row) - -drop table dest; -drop type textandtext; --- Tests for polymorphic-array form of width_bucket() --- this exercises the varwidth and float8 code paths -SELECT - op, - width_bucket(op::numeric, ARRAY[1, 3, 5, 10.0]::numeric[]) AS wb_n1, - width_bucket(op::numeric, ARRAY[0, 5.5, 9.99]::numeric[]) AS wb_n2, - width_bucket(op::numeric, ARRAY[-6, -5, 2.0]::numeric[]) AS wb_n3, - width_bucket(op::float8, ARRAY[1, 3, 5, 10.0]::float8[]) AS wb_f1, - width_bucket(op::float8, ARRAY[0, 5.5, 9.99]::float8[]) AS wb_f2, - width_bucket(op::float8, ARRAY[-6, -5, 2.0]::float8[]) AS wb_f3 -FROM (VALUES - (-5.2), - (-0.0000000001), - (0.000000000001), - (1), - (1.99999999999999), - (2), - (2.00000000000001), - (3), - (4), - (4.5), - (5), - (5.5), - (6), - (7), - (8), - (9), - (9.99999999999999), - (10), - (10.0000000000001) -) v(op); - op | wb_n1 | wb_n2 | wb_n3 | wb_f1 | wb_f2 | wb_f3 -------------------+-------+-------+-------+-------+-------+------- - -5.2 | 0 | 0 | 1 | 0 | 0 | 1 - -0.0000000001 | 0 | 0 | 2 | 0 | 0 | 2 - 0.000000000001 | 0 | 1 | 2 | 0 | 1 | 2 - 1 | 1 | 1 | 2 | 1 | 1 | 2 - 1.99999999999999 | 1 | 1 | 2 | 1 | 1 | 2 - 2 | 1 | 1 | 3 | 1 | 1 | 3 - 2.00000000000001 | 1 | 1 | 3 | 1 | 1 | 3 - 3 | 2 | 1 | 3 | 2 | 1 | 3 - 4 | 2 | 1 | 3 | 2 | 1 | 3 - 4.5 | 2 | 1 | 3 | 2 | 1 | 3 - 5 | 3 | 1 | 3 | 3 | 1 | 3 - 5.5 | 3 | 2 | 3 | 3 | 2 | 3 - 6 | 3 | 2 | 3 | 3 | 2 | 3 - 7 | 3 | 2 | 3 | 3 | 2 | 3 - 8 | 3 | 2 | 3 | 3 | 2 | 3 - 9 | 3 | 2 | 3 | 3 | 2 | 3 - 9.99999999999999 | 3 | 3 | 3 | 3 | 3 | 3 - 10 | 4 | 3 | 3 | 4 | 3 | 3 - 10.0000000000001 | 4 | 3 | 3 | 4 | 3 | 3 -(19 rows) - --- ensure float8 path handles NaN properly -SELECT - op, - width_bucket(op, ARRAY[1, 3, 9, 'NaN', 'NaN']::float8[]) AS wb -FROM (VALUES - (-5.2::float8), - (4::float8), - (77::float8), - ('NaN'::float8) -) v(op); - op | wb -------+---- - -5.2 | 0 - 4 | 2 - 77 | 3 - NaN | 5 -(4 rows) - --- these exercise the generic fixed-width code path -SELECT - op, - width_bucket(op, ARRAY[1, 3, 5, 10]) AS wb_1 -FROM generate_series(0,11) as op; - op | wb_1 -----+------ - 0 | 0 - 1 | 1 - 2 | 1 - 3 | 2 - 4 | 2 - 5 | 3 - 6 | 3 - 7 | 3 - 8 | 3 - 9 | 3 - 10 | 4 - 11 | 4 -(12 rows) - -SELECT width_bucket(now(), - array['yesterday', 'today', 'tomorrow']::timestamptz[]); - width_bucket --------------- - 2 -(1 row) - --- corner cases -SELECT width_bucket(5, ARRAY[3]); - width_bucket --------------- - 1 -(1 row) - -SELECT width_bucket(5, '{}'); - width_bucket --------------- - 0 -(1 row) - --- error cases -SELECT width_bucket('5'::text, ARRAY[3, 4]::integer[]); -ERROR: function width_bucket(text, integer[]) does not exist -LINE 1: SELECT width_bucket('5'::text, ARRAY[3, 4]::integer[]); - ^ -HINT: No function matches the given name and argument types. You might need to add explicit type casts. -SELECT width_bucket(5, ARRAY[3, 4, NULL]); -ERROR: thresholds array must not contain NULLs -SELECT width_bucket(5, ARRAY[ARRAY[1, 2], ARRAY[3, 4]]); -ERROR: thresholds must be one-dimensional array --- trim_array -SELECT arr, trim_array(arr, 2) -FROM -(VALUES ('{1,2,3,4,5,6}'::bigint[]), - ('{1,2}'), - ('[10:16]={1,2,3,4,5,6,7}'), - ('[-15:-10]={1,2,3,4,5,6}'), - ('{{1,10},{2,20},{3,30},{4,40}}')) v(arr); - arr | trim_array --------------------------------+----------------- - {1,2,3,4,5,6} | {1,2,3,4} - {1,2} | {} - [10:16]={1,2,3,4,5,6,7} | {1,2,3,4,5} - [-15:-10]={1,2,3,4,5,6} | {1,2,3,4} - {{1,10},{2,20},{3,30},{4,40}} | {{1,10},{2,20}} -(5 rows) - -SELECT trim_array(ARRAY[1, 2, 3], -1); -- fail -ERROR: number of elements to trim must be between 0 and 3 -SELECT trim_array(ARRAY[1, 2, 3], 10); -- fail -ERROR: number of elements to trim must be between 0 and 3 -SELECT trim_array(ARRAY[]::int[], 1); -- fail -ERROR: number of elements to trim must be between 0 and 0 --- array_shuffle -SELECT array_shuffle('{1,2,3,4,5,6}'::int[]) <@ '{1,2,3,4,5,6}'; - ?column? ----------- - t -(1 row) - -SELECT array_shuffle('{1,2,3,4,5,6}'::int[]) @> '{1,2,3,4,5,6}'; - ?column? ----------- - t -(1 row) - -SELECT array_dims(array_shuffle('[-1:2][2:3]={{1,2},{3,NULL},{5,6},{7,8}}'::int[])); - array_dims -------------- - [-1:2][2:3] -(1 row) - -SELECT array_dims(array_shuffle('{{{1,2},{3,NULL}},{{5,6},{7,8}},{{9,10},{11,12}}}'::int[])); - array_dims ------------------ - [1:3][1:2][1:2] -(1 row) - --- array_sample -SELECT array_sample('{1,2,3,4,5,6}'::int[], 3) <@ '{1,2,3,4,5,6}'; - ?column? ----------- - t -(1 row) - -SELECT array_length(array_sample('{1,2,3,4,5,6}'::int[], 3), 1); - array_length --------------- - 3 -(1 row) - -SELECT array_dims(array_sample('[-1:2][2:3]={{1,2},{3,NULL},{5,6},{7,8}}'::int[], 3)); - array_dims ------------- - [1:3][2:3] -(1 row) - -SELECT array_dims(array_sample('{{{1,2},{3,NULL}},{{5,6},{7,8}},{{9,10},{11,12}}}'::int[], 2)); - array_dims ------------------ - [1:2][1:2][1:2] -(1 row) - -SELECT array_sample('{1,2,3,4,5,6}'::int[], -1); -- fail -ERROR: sample size must be between 0 and 6 -SELECT array_sample('{1,2,3,4,5,6}'::int[], 7); --fail -ERROR: sample size must be between 0 and 6 +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/hash_index.out C:/cirrus/build/testrun/regress/regress/results/hash_index.out --- C:/cirrus/src/test/regress/expected/hash_index.out 2024-03-20 22:41:28.911520500 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/hash_index.out 2024-03-20 22:44:01.652405300 +0000 @@ -1,335 +1,2 @@ --- --- HASH_INDEX --- --- directory paths are passed to us in environment variables -\getenv abs_srcdir PG_ABS_SRCDIR -CREATE TABLE hash_i4_heap ( - seqno int4, - random int4 -); -CREATE TABLE hash_name_heap ( - seqno int4, - random name -); -CREATE TABLE hash_txt_heap ( - seqno int4, - random text -); -CREATE TABLE hash_f8_heap ( - seqno int4, - random float8 -); -\set filename :abs_srcdir '/data/hash.data' -COPY hash_i4_heap FROM :'filename'; -COPY hash_name_heap FROM :'filename'; -COPY hash_txt_heap FROM :'filename'; -COPY hash_f8_heap FROM :'filename'; --- the data in this file has a lot of duplicates in the index key --- fields, leading to long bucket chains and lots of table expansion. --- this is therefore a stress test of the bucket overflow code (unlike --- the data in hash.data, which has unique index keys). --- --- \set filename :abs_srcdir '/data/hashovfl.data' --- COPY hash_ovfl_heap FROM :'filename'; -ANALYZE hash_i4_heap; -ANALYZE hash_name_heap; -ANALYZE hash_txt_heap; -ANALYZE hash_f8_heap; -CREATE INDEX hash_i4_index ON hash_i4_heap USING hash (random int4_ops); -CREATE INDEX hash_name_index ON hash_name_heap USING hash (random name_ops); -CREATE INDEX hash_txt_index ON hash_txt_heap USING hash (random text_ops); -CREATE INDEX hash_f8_index ON hash_f8_heap USING hash (random float8_ops) - WITH (fillfactor=60); --- --- Also try building functional, expressional, and partial indexes on --- tables that already contain data. --- -create unique index hash_f8_index_1 on hash_f8_heap(abs(random)); -create unique index hash_f8_index_2 on hash_f8_heap((seqno + 1), random); -create unique index hash_f8_index_3 on hash_f8_heap(random) where seqno > 1000; --- --- hash index --- grep 843938989 hash.data --- -SELECT * FROM hash_i4_heap - WHERE hash_i4_heap.random = 843938989; - seqno | random --------+----------- - 15 | 843938989 -(1 row) - --- --- hash index --- grep 66766766 hash.data --- -SELECT * FROM hash_i4_heap - WHERE hash_i4_heap.random = 66766766; - seqno | random --------+-------- -(0 rows) - --- --- hash index --- grep 1505703298 hash.data --- -SELECT * FROM hash_name_heap - WHERE hash_name_heap.random = '1505703298'::name; - seqno | random --------+------------ - 9838 | 1505703298 -(1 row) - --- --- hash index --- grep 7777777 hash.data --- -SELECT * FROM hash_name_heap - WHERE hash_name_heap.random = '7777777'::name; - seqno | random --------+-------- -(0 rows) - --- --- hash index --- grep 1351610853 hash.data --- -SELECT * FROM hash_txt_heap - WHERE hash_txt_heap.random = '1351610853'::text; - seqno | random --------+------------ - 5677 | 1351610853 -(1 row) - --- --- hash index --- grep 111111112222222233333333 hash.data --- -SELECT * FROM hash_txt_heap - WHERE hash_txt_heap.random = '111111112222222233333333'::text; - seqno | random --------+-------- -(0 rows) - --- --- hash index --- grep 444705537 hash.data --- -SELECT * FROM hash_f8_heap - WHERE hash_f8_heap.random = '444705537'::float8; - seqno | random --------+----------- - 7853 | 444705537 -(1 row) - --- --- hash index --- grep 88888888 hash.data --- -SELECT * FROM hash_f8_heap - WHERE hash_f8_heap.random = '88888888'::float8; - seqno | random --------+-------- -(0 rows) - --- --- hash index --- grep '^90[^0-9]' hashovfl.data --- --- SELECT count(*) AS i988 FROM hash_ovfl_heap --- WHERE x = 90; --- --- hash index --- grep '^1000[^0-9]' hashovfl.data --- --- SELECT count(*) AS i0 FROM hash_ovfl_heap --- WHERE x = 1000; --- --- HASH --- -UPDATE hash_i4_heap - SET random = 1 - WHERE hash_i4_heap.seqno = 1492; -SELECT h.seqno AS i1492, h.random AS i1 - FROM hash_i4_heap h - WHERE h.random = 1; - i1492 | i1 --------+---- - 1492 | 1 -(1 row) - -UPDATE hash_i4_heap - SET seqno = 20000 - WHERE hash_i4_heap.random = 1492795354; -SELECT h.seqno AS i20000 - FROM hash_i4_heap h - WHERE h.random = 1492795354; - i20000 --------- - 20000 -(1 row) - -UPDATE hash_name_heap - SET random = '0123456789abcdef'::name - WHERE hash_name_heap.seqno = 6543; -SELECT h.seqno AS i6543, h.random AS c0_to_f - FROM hash_name_heap h - WHERE h.random = '0123456789abcdef'::name; - i6543 | c0_to_f --------+------------------ - 6543 | 0123456789abcdef -(1 row) - -UPDATE hash_name_heap - SET seqno = 20000 - WHERE hash_name_heap.random = '76652222'::name; --- --- this is the row we just replaced; index scan should return zero rows --- -SELECT h.seqno AS emptyset - FROM hash_name_heap h - WHERE h.random = '76652222'::name; - emptyset ----------- -(0 rows) - -UPDATE hash_txt_heap - SET random = '0123456789abcdefghijklmnop'::text - WHERE hash_txt_heap.seqno = 4002; -SELECT h.seqno AS i4002, h.random AS c0_to_p - FROM hash_txt_heap h - WHERE h.random = '0123456789abcdefghijklmnop'::text; - i4002 | c0_to_p --------+---------------------------- - 4002 | 0123456789abcdefghijklmnop -(1 row) - -UPDATE hash_txt_heap - SET seqno = 20000 - WHERE hash_txt_heap.random = '959363399'::text; -SELECT h.seqno AS t20000 - FROM hash_txt_heap h - WHERE h.random = '959363399'::text; - t20000 --------- - 20000 -(1 row) - -UPDATE hash_f8_heap - SET random = '-1234.1234'::float8 - WHERE hash_f8_heap.seqno = 8906; -SELECT h.seqno AS i8096, h.random AS f1234_1234 - FROM hash_f8_heap h - WHERE h.random = '-1234.1234'::float8; - i8096 | f1234_1234 --------+------------ - 8906 | -1234.1234 -(1 row) - -UPDATE hash_f8_heap - SET seqno = 20000 - WHERE hash_f8_heap.random = '488912369'::float8; -SELECT h.seqno AS f20000 - FROM hash_f8_heap h - WHERE h.random = '488912369'::float8; - f20000 --------- - 20000 -(1 row) - --- UPDATE hash_ovfl_heap --- SET x = 1000 --- WHERE x = 90; --- this vacuums the index as well --- VACUUM hash_ovfl_heap; --- SELECT count(*) AS i0 FROM hash_ovfl_heap --- WHERE x = 90; --- SELECT count(*) AS i988 FROM hash_ovfl_heap --- WHERE x = 1000; --- --- Cause some overflow insert and splits. --- -CREATE TABLE hash_split_heap (keycol INT); -INSERT INTO hash_split_heap SELECT 1 FROM generate_series(1, 500) a; -CREATE INDEX hash_split_index on hash_split_heap USING HASH (keycol); -INSERT INTO hash_split_heap SELECT 1 FROM generate_series(1, 5000) a; --- Let's do a backward scan. -BEGIN; -SET enable_seqscan = OFF; -SET enable_bitmapscan = OFF; -DECLARE c CURSOR FOR SELECT * from hash_split_heap WHERE keycol = 1; -MOVE FORWARD ALL FROM c; -MOVE BACKWARD 10000 FROM c; -MOVE BACKWARD ALL FROM c; -CLOSE c; -END; --- DELETE, INSERT, VACUUM. -DELETE FROM hash_split_heap WHERE keycol = 1; -INSERT INTO hash_split_heap SELECT a/2 FROM generate_series(1, 25000) a; -VACUUM hash_split_heap; --- Rebuild the index using a different fillfactor -ALTER INDEX hash_split_index SET (fillfactor = 10); -REINDEX INDEX hash_split_index; --- Clean up. -DROP TABLE hash_split_heap; --- Testcases for removing overflow pages. -CREATE TABLE hash_cleanup_heap(keycol INT); -CREATE INDEX hash_cleanup_index on hash_cleanup_heap USING HASH (keycol); --- Insert tuples to both the primary bucket page and overflow pages. -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i; --- Fill overflow pages by "dead" tuples. -BEGIN; -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1000) as i; -ROLLBACK; --- Checkpoint will ensure that all hash buffers are cleaned before we try --- to remove overflow pages. -CHECKPOINT; --- This will squeeze the bucket and remove overflow pages. -VACUUM hash_cleanup_heap; -TRUNCATE hash_cleanup_heap; --- Insert a few tuples so that the primary bucket page doesn't get full and --- tuples can be moved to it. -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 50) as i; --- Fill overflow pages by "dead" tuples. -BEGIN; -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1500) as i; -ROLLBACK; --- And insert some tuples again. During squeeze operation, these will be moved --- to the primary bucket allowing to test freeing intermediate overflow pages. -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i; -CHECKPOINT; -VACUUM hash_cleanup_heap; -TRUNCATE hash_cleanup_heap; --- Insert tuples to both the primary bucket page and overflow pages. -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 500) as i; --- Fill overflow pages by "dead" tuples. -BEGIN; -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 1500) as i; -ROLLBACK; --- And insert some tuples again. During squeeze operation, these will be moved --- to other overflow pages and also allow overflow pages filled by dead tuples --- to be freed. Note the main purpose of this test is to test the case where --- we don't need to move any tuple from the overflow page being freed. -INSERT INTO hash_cleanup_heap SELECT 1 FROM generate_series(1, 50) as i; -CHECKPOINT; -VACUUM hash_cleanup_heap; --- Clean up. -DROP TABLE hash_cleanup_heap; --- Index on temp table. -CREATE TEMP TABLE hash_temp_heap (x int, y int); -INSERT INTO hash_temp_heap VALUES (1,1); -CREATE INDEX hash_idx ON hash_temp_heap USING hash (x); -DROP TABLE hash_temp_heap CASCADE; --- Float4 type. -CREATE TABLE hash_heap_float4 (x float4, y int); -INSERT INTO hash_heap_float4 VALUES (1.1,1); -CREATE INDEX hash_idx ON hash_heap_float4 USING hash (x); -DROP TABLE hash_heap_float4 CASCADE; --- Test out-of-range fillfactor values -CREATE INDEX hash_f8_index2 ON hash_f8_heap USING hash (random float8_ops) - WITH (fillfactor=9); -ERROR: value 9 out of bounds for option "fillfactor" -DETAIL: Valid values are between "10" and "100". -CREATE INDEX hash_f8_index2 ON hash_f8_heap USING hash (random float8_ops) - WITH (fillfactor=101); -ERROR: value 101 out of bounds for option "fillfactor" -DETAIL: Valid values are between "10" and "100". +psql: error: connection to server on socket "c:/cirrus//.s.PGSQL.40048" failed: FATAL: the database system is not yet accepting connections +DETAIL: Consistent recovery state has not been yet reached. diff -w -U3 C:/cirrus/src/test/regress/expected/amutils.out C:/cirrus/build/testrun/regress/regress/results/amutils.out --- C:/cirrus/src/test/regress/expected/amutils.out 2024-03-20 22:41:28.840772800 +0000 +++ C:/cirrus/build/testrun/regress/regress/results/amutils.out 2024-03-20 22:44:27.612940500 +0000 @@ -93,20 +93,9 @@ 'bogus']::text[]) with ordinality as u(prop,ord) order by ord; - prop | btree | hash | gist | spgist_radix | spgist_quad | gin | brin ---------------------+-------+------+------+--------------+-------------+-----+------ - asc | t | f | f | f | f | f | f - desc | f | f | f | f | f | f | f - nulls_first | f | f | f | f | f | f | f - nulls_last | t | f | f | f | f | f | f - orderable | t | f | f | f | f | f | f - distance_orderable | f | f | t | f | t | f | f - returnable | t | f | f | t | t | f | f - search_array | t | f | f | f | f | f | f - search_nulls | t | f | t | t | t | f | t - bogus | | | | | | | -(10 rows) - +ERROR: relation "hash_i4_index" does not exist +LINE 3: pg_index_column_has_property('hash_i4_index'::regclas... + ^ select prop, pg_index_has_property('onek_hundred'::regclass, prop) as btree, pg_index_has_property('hash_i4_index'::regclass, prop) as hash, @@ -119,15 +108,9 @@ 'bogus']::text[]) with ordinality as u(prop,ord) order by ord; - prop | btree | hash | gist | spgist | gin | brin ----------------+-------+------+------+--------+-----+------ - clusterable | t | f | t | f | f | f - index_scan | t | t | t | t | f | f - bitmap_scan | t | t | t | t | t | t - backward_scan | t | t | f | f | f | f - bogus | | | | | | -(5 rows) - +ERROR: relation "hash_i4_index" does not exist +LINE 3: pg_index_has_property('hash_i4_index'::regclass, prop... + ^ select amname, prop, pg_indexam_has_property(a.oid, prop) as p from pg_am a, unnest(array['can_order', 'can_unique', 'can_multi_col',