]> granicus.if.org Git - postgresql/blob - src/test/regress/expected/with.out
Add CREATE RECURSIVE VIEW syntax
[postgresql] / src / test / regress / expected / with.out
1 --
2 -- Tests for common table expressions (WITH query, ... SELECT ...)
3 --
4 -- Basic WITH
5 WITH q1(x,y) AS (SELECT 1,2)
6 SELECT * FROM q1, q1 AS q2;
7  x | y | x | y 
8 ---+---+---+---
9  1 | 2 | 1 | 2
10 (1 row)
11
12 -- Multiple uses are evaluated only once
13 SELECT count(*) FROM (
14   WITH q1(x) AS (SELECT random() FROM generate_series(1, 5))
15     SELECT * FROM q1
16   UNION
17     SELECT * FROM q1
18 ) ss;
19  count 
20 -------
21      5
22 (1 row)
23
24 -- WITH RECURSIVE
25 -- sum of 1..100
26 WITH RECURSIVE t(n) AS (
27     VALUES (1)
28 UNION ALL
29     SELECT n+1 FROM t WHERE n < 100
30 )
31 SELECT sum(n) FROM t;
32  sum  
33 ------
34  5050
35 (1 row)
36
37 WITH RECURSIVE t(n) AS (
38     SELECT (VALUES(1))
39 UNION ALL
40     SELECT n+1 FROM t WHERE n < 5
41 )
42 SELECT * FROM t;
43  n 
44 ---
45  1
46  2
47  3
48  4
49  5
50 (5 rows)
51
52 -- recursive view
53 CREATE RECURSIVE VIEW nums (n) AS
54     VALUES (1)
55 UNION ALL
56     SELECT n+1 FROM nums WHERE n < 5;
57 SELECT * FROM nums;
58  n 
59 ---
60  1
61  2
62  3
63  4
64  5
65 (5 rows)
66
67 CREATE OR REPLACE RECURSIVE VIEW nums (n) AS
68     VALUES (1)
69 UNION ALL
70     SELECT n+1 FROM nums WHERE n < 6;
71 SELECT * FROM nums;
72  n 
73 ---
74  1
75  2
76  3
77  4
78  5
79  6
80 (6 rows)
81
82 -- This is an infinite loop with UNION ALL, but not with UNION
83 WITH RECURSIVE t(n) AS (
84     SELECT 1
85 UNION
86     SELECT 10-n FROM t)
87 SELECT * FROM t;
88  n 
89 ---
90  1
91  9
92 (2 rows)
93
94 -- This'd be an infinite loop, but outside query reads only as much as needed
95 WITH RECURSIVE t(n) AS (
96     VALUES (1)
97 UNION ALL
98     SELECT n+1 FROM t)
99 SELECT * FROM t LIMIT 10;
100  n  
101 ----
102   1
103   2
104   3
105   4
106   5
107   6
108   7
109   8
110   9
111  10
112 (10 rows)
113
114 -- UNION case should have same property
115 WITH RECURSIVE t(n) AS (
116     SELECT 1
117 UNION
118     SELECT n+1 FROM t)
119 SELECT * FROM t LIMIT 10;
120  n  
121 ----
122   1
123   2
124   3
125   4
126   5
127   6
128   7
129   8
130   9
131  10
132 (10 rows)
133
134 -- Test behavior with an unknown-type literal in the WITH
135 WITH q AS (SELECT 'foo' AS x)
136 SELECT x, x IS OF (unknown) as is_unknown FROM q;
137   x  | is_unknown 
138 -----+------------
139  foo | t
140 (1 row)
141
142 WITH RECURSIVE t(n) AS (
143     SELECT 'foo'
144 UNION ALL
145     SELECT n || ' bar' FROM t WHERE length(n) < 20
146 )
147 SELECT n, n IS OF (text) as is_text FROM t;
148             n            | is_text 
149 -------------------------+---------
150  foo                     | t
151  foo bar                 | t
152  foo bar bar             | t
153  foo bar bar bar         | t
154  foo bar bar bar bar     | t
155  foo bar bar bar bar bar | t
156 (6 rows)
157
158 --
159 -- Some examples with a tree
160 --
161 -- department structure represented here is as follows:
162 --
163 -- ROOT-+->A-+->B-+->C
164 --      |         |
165 --      |         +->D-+->F
166 --      +->E-+->G
167 CREATE TEMP TABLE department (
168         id INTEGER PRIMARY KEY,  -- department ID
169         parent_department INTEGER REFERENCES department, -- upper department ID
170         name TEXT -- department name
171 );
172 INSERT INTO department VALUES (0, NULL, 'ROOT');
173 INSERT INTO department VALUES (1, 0, 'A');
174 INSERT INTO department VALUES (2, 1, 'B');
175 INSERT INTO department VALUES (3, 2, 'C');
176 INSERT INTO department VALUES (4, 2, 'D');
177 INSERT INTO department VALUES (5, 0, 'E');
178 INSERT INTO department VALUES (6, 4, 'F');
179 INSERT INTO department VALUES (7, 5, 'G');
180 -- extract all departments under 'A'. Result should be A, B, C, D and F
181 WITH RECURSIVE subdepartment AS
182 (
183         -- non recursive term
184         SELECT name as root_name, * FROM department WHERE name = 'A'
185         UNION ALL
186         -- recursive term
187         SELECT sd.root_name, d.* FROM department AS d, subdepartment AS sd
188                 WHERE d.parent_department = sd.id
189 )
190 SELECT * FROM subdepartment ORDER BY name;
191  root_name | id | parent_department | name 
192 -----------+----+-------------------+------
193  A         |  1 |                 0 | A
194  A         |  2 |                 1 | B
195  A         |  3 |                 2 | C
196  A         |  4 |                 2 | D
197  A         |  6 |                 4 | F
198 (5 rows)
199
200 -- extract all departments under 'A' with "level" number
201 WITH RECURSIVE subdepartment(level, id, parent_department, name) AS
202 (
203         -- non recursive term
204         SELECT 1, * FROM department WHERE name = 'A'
205         UNION ALL
206         -- recursive term
207         SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd
208                 WHERE d.parent_department = sd.id
209 )
210 SELECT * FROM subdepartment ORDER BY name;
211  level | id | parent_department | name 
212 -------+----+-------------------+------
213      1 |  1 |                 0 | A
214      2 |  2 |                 1 | B
215      3 |  3 |                 2 | C
216      3 |  4 |                 2 | D
217      4 |  6 |                 4 | F
218 (5 rows)
219
220 -- extract all departments under 'A' with "level" number.
221 -- Only shows level 2 or more
222 WITH RECURSIVE subdepartment(level, id, parent_department, name) AS
223 (
224         -- non recursive term
225         SELECT 1, * FROM department WHERE name = 'A'
226         UNION ALL
227         -- recursive term
228         SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd
229                 WHERE d.parent_department = sd.id
230 )
231 SELECT * FROM subdepartment WHERE level >= 2 ORDER BY name;
232  level | id | parent_department | name 
233 -------+----+-------------------+------
234      2 |  2 |                 1 | B
235      3 |  3 |                 2 | C
236      3 |  4 |                 2 | D
237      4 |  6 |                 4 | F
238 (4 rows)
239
240 -- "RECURSIVE" is ignored if the query has no self-reference
241 WITH RECURSIVE subdepartment AS
242 (
243         -- note lack of recursive UNION structure
244         SELECT * FROM department WHERE name = 'A'
245 )
246 SELECT * FROM subdepartment ORDER BY name;
247  id | parent_department | name 
248 ----+-------------------+------
249   1 |                 0 | A
250 (1 row)
251
252 -- inside subqueries
253 SELECT count(*) FROM (
254     WITH RECURSIVE t(n) AS (
255         SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 500
256     )
257     SELECT * FROM t) AS t WHERE n < (
258         SELECT count(*) FROM (
259             WITH RECURSIVE t(n) AS (
260                    SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 100
261                 )
262             SELECT * FROM t WHERE n < 50000
263          ) AS t WHERE n < 100);
264  count 
265 -------
266     98
267 (1 row)
268
269 -- use same CTE twice at different subquery levels
270 WITH q1(x,y) AS (
271     SELECT hundred, sum(ten) FROM tenk1 GROUP BY hundred
272   )
273 SELECT count(*) FROM q1 WHERE y > (SELECT sum(y)/100 FROM q1 qsub);
274  count 
275 -------
276     50
277 (1 row)
278
279 -- via a VIEW
280 CREATE TEMPORARY VIEW vsubdepartment AS
281         WITH RECURSIVE subdepartment AS
282         (
283                  -- non recursive term
284                 SELECT * FROM department WHERE name = 'A'
285                 UNION ALL
286                 -- recursive term
287                 SELECT d.* FROM department AS d, subdepartment AS sd
288                         WHERE d.parent_department = sd.id
289         )
290         SELECT * FROM subdepartment;
291 SELECT * FROM vsubdepartment ORDER BY name;
292  id | parent_department | name 
293 ----+-------------------+------
294   1 |                 0 | A
295   2 |                 1 | B
296   3 |                 2 | C
297   4 |                 2 | D
298   6 |                 4 | F
299 (5 rows)
300
301 -- Check reverse listing
302 SELECT pg_get_viewdef('vsubdepartment'::regclass);
303                                                                                                                                                                                     pg_get_viewdef                                                                                                                                                                                     
304 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
305  WITH RECURSIVE subdepartment AS (SELECT department.id, department.parent_department, department.name FROM department WHERE (department.name = 'A'::text) UNION ALL SELECT d.id, d.parent_department, d.name FROM department d, subdepartment sd WHERE (d.parent_department = sd.id)) SELECT subdepartment.id, subdepartment.parent_department, subdepartment.name FROM subdepartment;
306 (1 row)
307
308 SELECT pg_get_viewdef('vsubdepartment'::regclass, true);
309                                 pg_get_viewdef                                 
310 -------------------------------------------------------------------------------
311   WITH RECURSIVE subdepartment AS (                                           +
312                   SELECT department.id, department.parent_department,         +
313                      department.name                                          +
314                     FROM department                                           +
315                    WHERE department.name = 'A'::text                          +
316          UNION ALL                                                            +
317                   SELECT d.id, d.parent_department, d.name                    +
318                     FROM department d, subdepartment sd                       +
319                    WHERE d.parent_department = sd.id                          +
320          )                                                                    +
321   SELECT subdepartment.id, subdepartment.parent_department, subdepartment.name+
322     FROM subdepartment;
323 (1 row)
324
325 -- Another reverse-listing example
326 CREATE VIEW sums_1_100 AS
327 WITH RECURSIVE t(n) AS (
328     VALUES (1)
329 UNION ALL
330     SELECT n+1 FROM t WHERE n < 100
331 )
332 SELECT sum(n) FROM t;
333 \d+ sums_1_100
334               View "public.sums_1_100"
335  Column |  Type  | Modifiers | Storage | Description 
336 --------+--------+-----------+---------+-------------
337  sum    | bigint |           | plain   | 
338 View definition:
339  WITH RECURSIVE t(n) AS (
340                  VALUES (1)
341         UNION ALL 
342                  SELECT t_1.n + 1
343                    FROM t t_1
344                   WHERE t_1.n < 100
345         )
346  SELECT sum(t.n) AS sum
347    FROM t;
348
349 -- corner case in which sub-WITH gets initialized first
350 with recursive q as (
351       select * from department
352     union all
353       (with x as (select * from q)
354        select * from x)
355     )
356 select * from q limit 24;
357  id | parent_department | name 
358 ----+-------------------+------
359   0 |                   | ROOT
360   1 |                 0 | A
361   2 |                 1 | B
362   3 |                 2 | C
363   4 |                 2 | D
364   5 |                 0 | E
365   6 |                 4 | F
366   7 |                 5 | G
367   0 |                   | ROOT
368   1 |                 0 | A
369   2 |                 1 | B
370   3 |                 2 | C
371   4 |                 2 | D
372   5 |                 0 | E
373   6 |                 4 | F
374   7 |                 5 | G
375   0 |                   | ROOT
376   1 |                 0 | A
377   2 |                 1 | B
378   3 |                 2 | C
379   4 |                 2 | D
380   5 |                 0 | E
381   6 |                 4 | F
382   7 |                 5 | G
383 (24 rows)
384
385 with recursive q as (
386       select * from department
387     union all
388       (with recursive x as (
389            select * from department
390          union all
391            (select * from q union all select * from x)
392         )
393        select * from x)
394     )
395 select * from q limit 32;
396  id | parent_department | name 
397 ----+-------------------+------
398   0 |                   | ROOT
399   1 |                 0 | A
400   2 |                 1 | B
401   3 |                 2 | C
402   4 |                 2 | D
403   5 |                 0 | E
404   6 |                 4 | F
405   7 |                 5 | G
406   0 |                   | ROOT
407   1 |                 0 | A
408   2 |                 1 | B
409   3 |                 2 | C
410   4 |                 2 | D
411   5 |                 0 | E
412   6 |                 4 | F
413   7 |                 5 | G
414   0 |                   | ROOT
415   1 |                 0 | A
416   2 |                 1 | B
417   3 |                 2 | C
418   4 |                 2 | D
419   5 |                 0 | E
420   6 |                 4 | F
421   7 |                 5 | G
422   0 |                   | ROOT
423   1 |                 0 | A
424   2 |                 1 | B
425   3 |                 2 | C
426   4 |                 2 | D
427   5 |                 0 | E
428   6 |                 4 | F
429   7 |                 5 | G
430 (32 rows)
431
432 -- recursive term has sub-UNION
433 WITH RECURSIVE t(i,j) AS (
434         VALUES (1,2)
435         UNION ALL
436         SELECT t2.i, t.j+1 FROM
437                 (SELECT 2 AS i UNION ALL SELECT 3 AS i) AS t2
438                 JOIN t ON (t2.i = t.i+1))
439         SELECT * FROM t;
440  i | j 
441 ---+---
442  1 | 2
443  2 | 3
444  3 | 4
445 (3 rows)
446
447 --
448 -- different tree example
449 --
450 CREATE TEMPORARY TABLE tree(
451     id INTEGER PRIMARY KEY,
452     parent_id INTEGER REFERENCES tree(id)
453 );
454 INSERT INTO tree
455 VALUES (1, NULL), (2, 1), (3,1), (4,2), (5,2), (6,2), (7,3), (8,3),
456        (9,4), (10,4), (11,7), (12,7), (13,7), (14, 9), (15,11), (16,11);
457 --
458 -- get all paths from "second level" nodes to leaf nodes
459 --
460 WITH RECURSIVE t(id, path) AS (
461     VALUES(1,ARRAY[]::integer[])
462 UNION ALL
463     SELECT tree.id, t.path || tree.id
464     FROM tree JOIN t ON (tree.parent_id = t.id)
465 )
466 SELECT t1.*, t2.* FROM t AS t1 JOIN t AS t2 ON
467         (t1.path[1] = t2.path[1] AND
468         array_upper(t1.path,1) = 1 AND
469         array_upper(t2.path,1) > 1)
470         ORDER BY t1.id, t2.id;
471  id | path | id |    path     
472 ----+------+----+-------------
473   2 | {2}  |  4 | {2,4}
474   2 | {2}  |  5 | {2,5}
475   2 | {2}  |  6 | {2,6}
476   2 | {2}  |  9 | {2,4,9}
477   2 | {2}  | 10 | {2,4,10}
478   2 | {2}  | 14 | {2,4,9,14}
479   3 | {3}  |  7 | {3,7}
480   3 | {3}  |  8 | {3,8}
481   3 | {3}  | 11 | {3,7,11}
482   3 | {3}  | 12 | {3,7,12}
483   3 | {3}  | 13 | {3,7,13}
484   3 | {3}  | 15 | {3,7,11,15}
485   3 | {3}  | 16 | {3,7,11,16}
486 (13 rows)
487
488 -- just count 'em
489 WITH RECURSIVE t(id, path) AS (
490     VALUES(1,ARRAY[]::integer[])
491 UNION ALL
492     SELECT tree.id, t.path || tree.id
493     FROM tree JOIN t ON (tree.parent_id = t.id)
494 )
495 SELECT t1.id, count(t2.*) FROM t AS t1 JOIN t AS t2 ON
496         (t1.path[1] = t2.path[1] AND
497         array_upper(t1.path,1) = 1 AND
498         array_upper(t2.path,1) > 1)
499         GROUP BY t1.id
500         ORDER BY t1.id;
501  id | count 
502 ----+-------
503   2 |     6
504   3 |     7
505 (2 rows)
506
507 -- this variant tickled a whole-row-variable bug in 8.4devel
508 WITH RECURSIVE t(id, path) AS (
509     VALUES(1,ARRAY[]::integer[])
510 UNION ALL
511     SELECT tree.id, t.path || tree.id
512     FROM tree JOIN t ON (tree.parent_id = t.id)
513 )
514 SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON
515 (t1.id=t2.id);
516  id |    path     |         t2         
517 ----+-------------+--------------------
518   1 | {}          | (1,{})
519   2 | {2}         | (2,{2})
520   3 | {3}         | (3,{3})
521   4 | {2,4}       | (4,"{2,4}")
522   5 | {2,5}       | (5,"{2,5}")
523   6 | {2,6}       | (6,"{2,6}")
524   7 | {3,7}       | (7,"{3,7}")
525   8 | {3,8}       | (8,"{3,8}")
526   9 | {2,4,9}     | (9,"{2,4,9}")
527  10 | {2,4,10}    | (10,"{2,4,10}")
528  11 | {3,7,11}    | (11,"{3,7,11}")
529  12 | {3,7,12}    | (12,"{3,7,12}")
530  13 | {3,7,13}    | (13,"{3,7,13}")
531  14 | {2,4,9,14}  | (14,"{2,4,9,14}")
532  15 | {3,7,11,15} | (15,"{3,7,11,15}")
533  16 | {3,7,11,16} | (16,"{3,7,11,16}")
534 (16 rows)
535
536 --
537 -- test cycle detection
538 --
539 create temp table graph( f int, t int, label text );
540 insert into graph values
541         (1, 2, 'arc 1 -> 2'),
542         (1, 3, 'arc 1 -> 3'),
543         (2, 3, 'arc 2 -> 3'),
544         (1, 4, 'arc 1 -> 4'),
545         (4, 5, 'arc 4 -> 5'),
546         (5, 1, 'arc 5 -> 1');
547 with recursive search_graph(f, t, label, path, cycle) as (
548         select *, array[row(g.f, g.t)], false from graph g
549         union all
550         select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
551         from graph g, search_graph sg
552         where g.f = sg.t and not cycle
553 )
554 select * from search_graph;
555  f | t |   label    |                   path                    | cycle 
556 ---+---+------------+-------------------------------------------+-------
557  1 | 2 | arc 1 -> 2 | {"(1,2)"}                                 | f
558  1 | 3 | arc 1 -> 3 | {"(1,3)"}                                 | f
559  2 | 3 | arc 2 -> 3 | {"(2,3)"}                                 | f
560  1 | 4 | arc 1 -> 4 | {"(1,4)"}                                 | f
561  4 | 5 | arc 4 -> 5 | {"(4,5)"}                                 | f
562  5 | 1 | arc 5 -> 1 | {"(5,1)"}                                 | f
563  1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"}                         | f
564  1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"}                         | f
565  1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"}                         | f
566  2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}                         | f
567  4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}                         | f
568  5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"}                         | f
569  1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"}                 | f
570  1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"}                 | f
571  1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"}                 | f
572  2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"}                 | f
573  4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"}                 | f
574  5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"}                 | f
575  1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"}         | f
576  1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"}         | f
577  1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"}         | t
578  2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"}         | f
579  4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"}         | t
580  5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"}         | t
581  2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
582 (25 rows)
583
584 -- ordering by the path column has same effect as SEARCH DEPTH FIRST
585 with recursive search_graph(f, t, label, path, cycle) as (
586         select *, array[row(g.f, g.t)], false from graph g
587         union all
588         select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
589         from graph g, search_graph sg
590         where g.f = sg.t and not cycle
591 )
592 select * from search_graph order by path;
593  f | t |   label    |                   path                    | cycle 
594 ---+---+------------+-------------------------------------------+-------
595  1 | 2 | arc 1 -> 2 | {"(1,2)"}                                 | f
596  2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}                         | f
597  1 | 3 | arc 1 -> 3 | {"(1,3)"}                                 | f
598  1 | 4 | arc 1 -> 4 | {"(1,4)"}                                 | f
599  4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}                         | f
600  5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"}                 | f
601  1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"}         | f
602  2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
603  1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"}         | f
604  1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"}         | t
605  2 | 3 | arc 2 -> 3 | {"(2,3)"}                                 | f
606  4 | 5 | arc 4 -> 5 | {"(4,5)"}                                 | f
607  5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"}                         | f
608  1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"}                 | f
609  2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"}         | f
610  1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"}                 | f
611  1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"}                 | f
612  4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"}         | t
613  5 | 1 | arc 5 -> 1 | {"(5,1)"}                                 | f
614  1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"}                         | f
615  2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"}                 | f
616  1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"}                         | f
617  1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"}                         | f
618  4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"}                 | f
619  5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"}         | t
620 (25 rows)
621
622 --
623 -- test multiple WITH queries
624 --
625 WITH RECURSIVE
626   y (id) AS (VALUES (1)),
627   x (id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5)
628 SELECT * FROM x;
629  id 
630 ----
631   1
632   2
633   3
634   4
635   5
636 (5 rows)
637
638 -- forward reference OK
639 WITH RECURSIVE
640     x(id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5),
641     y(id) AS (values (1))
642  SELECT * FROM x;
643  id 
644 ----
645   1
646   2
647   3
648   4
649   5
650 (5 rows)
651
652 WITH RECURSIVE
653    x(id) AS
654      (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5),
655    y(id) AS
656      (VALUES (1) UNION ALL SELECT id+1 FROM y WHERE id < 10)
657  SELECT y.*, x.* FROM y LEFT JOIN x USING (id);
658  id | id 
659 ----+----
660   1 |  1
661   2 |  2
662   3 |  3
663   4 |  4
664   5 |  5
665   6 |   
666   7 |   
667   8 |   
668   9 |   
669  10 |   
670 (10 rows)
671
672 WITH RECURSIVE
673    x(id) AS
674      (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5),
675    y(id) AS
676      (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 10)
677  SELECT y.*, x.* FROM y LEFT JOIN x USING (id);
678  id | id 
679 ----+----
680   1 |  1
681   2 |  2
682   3 |  3
683   4 |  4
684   5 |  5
685   6 |   
686 (6 rows)
687
688 WITH RECURSIVE
689    x(id) AS
690      (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ),
691    y(id) AS
692      (SELECT * FROM x UNION ALL SELECT * FROM x),
693    z(id) AS
694      (SELECT * FROM x UNION ALL SELECT id+1 FROM z WHERE id < 10)
695  SELECT * FROM z;
696  id 
697 ----
698   1
699   2
700   3
701   2
702   3
703   4
704   3
705   4
706   5
707   4
708   5
709   6
710   5
711   6
712   7
713   6
714   7
715   8
716   7
717   8
718   9
719   8
720   9
721  10
722   9
723  10
724  10
725 (27 rows)
726
727 WITH RECURSIVE
728    x(id) AS
729      (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ),
730    y(id) AS
731      (SELECT * FROM x UNION ALL SELECT * FROM x),
732    z(id) AS
733      (SELECT * FROM y UNION ALL SELECT id+1 FROM z WHERE id < 10)
734  SELECT * FROM z;
735  id 
736 ----
737   1
738   2
739   3
740   1
741   2
742   3
743   2
744   3
745   4
746   2
747   3
748   4
749   3
750   4
751   5
752   3
753   4
754   5
755   4
756   5
757   6
758   4
759   5
760   6
761   5
762   6
763   7
764   5
765   6
766   7
767   6
768   7
769   8
770   6
771   7
772   8
773   7
774   8
775   9
776   7
777   8
778   9
779   8
780   9
781  10
782   8
783   9
784  10
785   9
786  10
787   9
788  10
789  10
790  10
791 (54 rows)
792
793 --
794 -- Test WITH attached to a data-modifying statement
795 --
796 CREATE TEMPORARY TABLE y (a INTEGER);
797 INSERT INTO y SELECT generate_series(1, 10);
798 WITH t AS (
799         SELECT a FROM y
800 )
801 INSERT INTO y
802 SELECT a+20 FROM t RETURNING *;
803  a  
804 ----
805  21
806  22
807  23
808  24
809  25
810  26
811  27
812  28
813  29
814  30
815 (10 rows)
816
817 SELECT * FROM y;
818  a  
819 ----
820   1
821   2
822   3
823   4
824   5
825   6
826   7
827   8
828   9
829  10
830  21
831  22
832  23
833  24
834  25
835  26
836  27
837  28
838  29
839  30
840 (20 rows)
841
842 WITH t AS (
843         SELECT a FROM y
844 )
845 UPDATE y SET a = y.a-10 FROM t WHERE y.a > 20 AND t.a = y.a RETURNING y.a;
846  a  
847 ----
848  11
849  12
850  13
851  14
852  15
853  16
854  17
855  18
856  19
857  20
858 (10 rows)
859
860 SELECT * FROM y;
861  a  
862 ----
863   1
864   2
865   3
866   4
867   5
868   6
869   7
870   8
871   9
872  10
873  11
874  12
875  13
876  14
877  15
878  16
879  17
880  18
881  19
882  20
883 (20 rows)
884
885 WITH RECURSIVE t(a) AS (
886         SELECT 11
887         UNION ALL
888         SELECT a+1 FROM t WHERE a < 50
889 )
890 DELETE FROM y USING t WHERE t.a = y.a RETURNING y.a;
891  a  
892 ----
893  11
894  12
895  13
896  14
897  15
898  16
899  17
900  18
901  19
902  20
903 (10 rows)
904
905 SELECT * FROM y;
906  a  
907 ----
908   1
909   2
910   3
911   4
912   5
913   6
914   7
915   8
916   9
917  10
918 (10 rows)
919
920 DROP TABLE y;
921 --
922 -- error cases
923 --
924 -- INTERSECT
925 WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
926         SELECT * FROM x;
927 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
928 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x...
929                        ^
930 WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FROM x)
931         SELECT * FROM x;
932 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
933 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FR...
934                        ^
935 -- EXCEPT
936 WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x)
937         SELECT * FROM x;
938 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
939 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x)
940                        ^
941 WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM x)
942         SELECT * FROM x;
943 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
944 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM ...
945                        ^
946 -- no non-recursive term
947 WITH RECURSIVE x(n) AS (SELECT n FROM x)
948         SELECT * FROM x;
949 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
950 LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x)
951                        ^
952 -- recursive term in the left hand side (strictly speaking, should allow this)
953 WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
954         SELECT * FROM x;
955 ERROR:  recursive reference to query "x" must not appear within its non-recursive term
956 LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
957                                               ^
958 CREATE TEMPORARY TABLE y (a INTEGER);
959 INSERT INTO y SELECT generate_series(1, 10);
960 -- LEFT JOIN
961 WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
962         UNION ALL
963         SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10)
964 SELECT * FROM x;
965 ERROR:  recursive reference to query "x" must not appear within an outer join
966 LINE 3:  SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10)
967                                        ^
968 -- RIGHT JOIN
969 WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
970         UNION ALL
971         SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10)
972 SELECT * FROM x;
973 ERROR:  recursive reference to query "x" must not appear within an outer join
974 LINE 3:  SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10)
975                            ^
976 -- FULL JOIN
977 WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
978         UNION ALL
979         SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10)
980 SELECT * FROM x;
981 ERROR:  recursive reference to query "x" must not appear within an outer join
982 LINE 3:  SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10)
983                            ^
984 -- subquery
985 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x
986                           WHERE n IN (SELECT * FROM x))
987   SELECT * FROM x;
988 ERROR:  recursive reference to query "x" must not appear within a subquery
989 LINE 2:                           WHERE n IN (SELECT * FROM x))
990                                                             ^
991 -- aggregate functions
992 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) FROM x)
993   SELECT * FROM x;
994 ERROR:  aggregate functions are not allowed in a recursive query's recursive term
995 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) F...
996                                                           ^
997 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FROM x)
998   SELECT * FROM x;
999 ERROR:  aggregate functions are not allowed in a recursive query's recursive term
1000 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FRO...
1001                                                           ^
1002 -- ORDER BY
1003 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1)
1004   SELECT * FROM x;
1005 ERROR:  ORDER BY in a recursive query is not implemented
1006 LINE 1: ...VE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1)
1007                                                                      ^
1008 -- LIMIT/OFFSET
1009 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1)
1010   SELECT * FROM x;
1011 ERROR:  OFFSET in a recursive query is not implemented
1012 LINE 1: ... AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1)
1013                                                                      ^
1014 -- FOR UPDATE
1015 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x FOR UPDATE)
1016   SELECT * FROM x;
1017 ERROR:  FOR UPDATE/SHARE in a recursive query is not implemented
1018 -- target list has a recursive query name
1019 WITH RECURSIVE x(id) AS (values (1)
1020     UNION ALL
1021     SELECT (SELECT * FROM x) FROM x WHERE id < 5
1022 ) SELECT * FROM x;
1023 ERROR:  recursive reference to query "x" must not appear within a subquery
1024 LINE 3:     SELECT (SELECT * FROM x) FROM x WHERE id < 5
1025                                   ^
1026 -- mutual recursive query (not implemented)
1027 WITH RECURSIVE
1028   x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id < 5),
1029   y (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 5)
1030 SELECT * FROM x;
1031 ERROR:  mutual recursion between WITH items is not implemented
1032 LINE 2:   x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id ...
1033           ^
1034 -- non-linear recursion is not allowed
1035 WITH RECURSIVE foo(i) AS
1036     (values (1)
1037     UNION ALL
1038        (SELECT i+1 FROM foo WHERE i < 10
1039           UNION ALL
1040        SELECT i+1 FROM foo WHERE i < 5)
1041 ) SELECT * FROM foo;
1042 ERROR:  recursive reference to query "foo" must not appear more than once
1043 LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
1044                                ^
1045 WITH RECURSIVE foo(i) AS
1046     (values (1)
1047     UNION ALL
1048            SELECT * FROM
1049        (SELECT i+1 FROM foo WHERE i < 10
1050           UNION ALL
1051        SELECT i+1 FROM foo WHERE i < 5) AS t
1052 ) SELECT * FROM foo;
1053 ERROR:  recursive reference to query "foo" must not appear more than once
1054 LINE 7:        SELECT i+1 FROM foo WHERE i < 5) AS t
1055                                ^
1056 WITH RECURSIVE foo(i) AS
1057     (values (1)
1058     UNION ALL
1059        (SELECT i+1 FROM foo WHERE i < 10
1060           EXCEPT
1061        SELECT i+1 FROM foo WHERE i < 5)
1062 ) SELECT * FROM foo;
1063 ERROR:  recursive reference to query "foo" must not appear within EXCEPT
1064 LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
1065                                ^
1066 WITH RECURSIVE foo(i) AS
1067     (values (1)
1068     UNION ALL
1069        (SELECT i+1 FROM foo WHERE i < 10
1070           INTERSECT
1071        SELECT i+1 FROM foo WHERE i < 5)
1072 ) SELECT * FROM foo;
1073 ERROR:  recursive reference to query "foo" must not appear more than once
1074 LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
1075                                ^
1076 -- Wrong type induced from non-recursive term
1077 WITH RECURSIVE foo(i) AS
1078    (SELECT i FROM (VALUES(1),(2)) t(i)
1079    UNION ALL
1080    SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
1081 SELECT * FROM foo;
1082 ERROR:  recursive query "foo" column 1 has type integer in non-recursive term but type numeric overall
1083 LINE 2:    (SELECT i FROM (VALUES(1),(2)) t(i)
1084                    ^
1085 HINT:  Cast the output of the non-recursive term to the correct type.
1086 -- rejects different typmod, too (should we allow this?)
1087 WITH RECURSIVE foo(i) AS
1088    (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
1089    UNION ALL
1090    SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
1091 SELECT * FROM foo;
1092 ERROR:  recursive query "foo" column 1 has type numeric(3,0) in non-recursive term but type numeric overall
1093 LINE 2:    (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
1094                    ^
1095 HINT:  Cast the output of the non-recursive term to the correct type.
1096 -- disallow OLD/NEW reference in CTE
1097 CREATE TEMPORARY TABLE x (n integer);
1098 CREATE RULE r2 AS ON UPDATE TO x DO INSTEAD
1099     WITH t AS (SELECT OLD.*) UPDATE y SET a = t.n FROM t;
1100 ERROR:  cannot refer to OLD within WITH query
1101 --
1102 -- test for bug #4902
1103 --
1104 with cte(foo) as ( values(42) ) values((select foo from cte));
1105  column1 
1106 ---------
1107       42
1108 (1 row)
1109
1110 with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q;
1111  foo 
1112 -----
1113   42
1114 (1 row)
1115
1116 -- test CTE referencing an outer-level variable (to see that changed-parameter
1117 -- signaling still works properly after fixing this bug)
1118 select ( with cte(foo) as ( values(f1) )
1119          select (select foo from cte) )
1120 from int4_tbl;
1121      foo     
1122 -------------
1123            0
1124       123456
1125      -123456
1126   2147483647
1127  -2147483647
1128 (5 rows)
1129
1130 select ( with cte(foo) as ( values(f1) )
1131           values((select foo from cte)) )
1132 from int4_tbl;
1133    column1   
1134 -------------
1135            0
1136       123456
1137      -123456
1138   2147483647
1139  -2147483647
1140 (5 rows)
1141
1142 --
1143 -- test for nested-recursive-WITH bug
1144 --
1145 WITH RECURSIVE t(j) AS (
1146     WITH RECURSIVE s(i) AS (
1147         VALUES (1)
1148         UNION ALL
1149         SELECT i+1 FROM s WHERE i < 10
1150     )
1151     SELECT i FROM s
1152     UNION ALL
1153     SELECT j+1 FROM t WHERE j < 10
1154 )
1155 SELECT * FROM t;
1156  j  
1157 ----
1158   1
1159   2
1160   3
1161   4
1162   5
1163   6
1164   7
1165   8
1166   9
1167  10
1168   2
1169   3
1170   4
1171   5
1172   6
1173   7
1174   8
1175   9
1176  10
1177   3
1178   4
1179   5
1180   6
1181   7
1182   8
1183   9
1184  10
1185   4
1186   5
1187   6
1188   7
1189   8
1190   9
1191  10
1192   5
1193   6
1194   7
1195   8
1196   9
1197  10
1198   6
1199   7
1200   8
1201   9
1202  10
1203   7
1204   8
1205   9
1206  10
1207   8
1208   9
1209  10
1210   9
1211  10
1212  10
1213 (55 rows)
1214
1215 --
1216 -- test WITH attached to intermediate-level set operation
1217 --
1218 WITH outermost(x) AS (
1219   SELECT 1
1220   UNION (WITH innermost as (SELECT 2)
1221          SELECT * FROM innermost
1222          UNION SELECT 3)
1223 )
1224 SELECT * FROM outermost;
1225  x 
1226 ---
1227  1
1228  2
1229  3
1230 (3 rows)
1231
1232 WITH outermost(x) AS (
1233   SELECT 1
1234   UNION (WITH innermost as (SELECT 2)
1235          SELECT * FROM outermost  -- fail
1236          UNION SELECT * FROM innermost)
1237 )
1238 SELECT * FROM outermost;
1239 ERROR:  relation "outermost" does not exist
1240 LINE 4:          SELECT * FROM outermost  
1241                                ^
1242 DETAIL:  There is a WITH item named "outermost", but it cannot be referenced from this part of the query.
1243 HINT:  Use WITH RECURSIVE, or re-order the WITH items to remove forward references.
1244 WITH RECURSIVE outermost(x) AS (
1245   SELECT 1
1246   UNION (WITH innermost as (SELECT 2)
1247          SELECT * FROM outermost
1248          UNION SELECT * FROM innermost)
1249 )
1250 SELECT * FROM outermost;
1251  x 
1252 ---
1253  1
1254  2
1255 (2 rows)
1256
1257 WITH RECURSIVE outermost(x) AS (
1258   WITH innermost as (SELECT 2 FROM outermost) -- fail
1259     SELECT * FROM innermost
1260     UNION SELECT * from outermost
1261 )
1262 SELECT * FROM outermost;
1263 ERROR:  recursive reference to query "outermost" must not appear within a subquery
1264 LINE 2:   WITH innermost as (SELECT 2 FROM outermost) 
1265                                            ^
1266 --
1267 -- This test will fail with the old implementation of PARAM_EXEC parameter
1268 -- assignment, because the "q1" Var passed down to A's targetlist subselect
1269 -- looks exactly like the "A.id" Var passed down to C's subselect, causing
1270 -- the old code to give them the same runtime PARAM_EXEC slot.  But the
1271 -- lifespans of the two parameters overlap, thanks to B also reading A.
1272 --
1273 with
1274 A as ( select q2 as id, (select q1) as x from int8_tbl ),
1275 B as ( select id, row_number() over (partition by id) as r from A ),
1276 C as ( select A.id, array(select B.id from B where B.id = A.id) from A )
1277 select * from C;
1278         id         |                array                
1279 -------------------+-------------------------------------
1280                456 | {456}
1281   4567890123456789 | {4567890123456789,4567890123456789}
1282                123 | {123}
1283   4567890123456789 | {4567890123456789,4567890123456789}
1284  -4567890123456789 | {-4567890123456789}
1285 (5 rows)
1286
1287 --
1288 -- Test CTEs read in non-initialization orders
1289 --
1290 WITH RECURSIVE
1291   tab(id_key,link) AS (VALUES (1,17), (2,17), (3,17), (4,17), (6,17), (5,17)),
1292   iter (id_key, row_type, link) AS (
1293       SELECT 0, 'base', 17
1294     UNION ALL (
1295       WITH remaining(id_key, row_type, link, min) AS (
1296         SELECT tab.id_key, 'true'::text, iter.link, MIN(tab.id_key) OVER ()
1297         FROM tab INNER JOIN iter USING (link)
1298         WHERE tab.id_key > iter.id_key
1299       ),
1300       first_remaining AS (
1301         SELECT id_key, row_type, link
1302         FROM remaining
1303         WHERE id_key=min
1304       ),
1305       effect AS (
1306         SELECT tab.id_key, 'new'::text, tab.link
1307         FROM first_remaining e INNER JOIN tab ON e.id_key=tab.id_key
1308         WHERE e.row_type = 'false'
1309       )
1310       SELECT * FROM first_remaining
1311       UNION ALL SELECT * FROM effect
1312     )
1313   )
1314 SELECT * FROM iter;
1315  id_key | row_type | link 
1316 --------+----------+------
1317       0 | base     |   17
1318       1 | true     |   17
1319       2 | true     |   17
1320       3 | true     |   17
1321       4 | true     |   17
1322       5 | true     |   17
1323       6 | true     |   17
1324 (7 rows)
1325
1326 WITH RECURSIVE
1327   tab(id_key,link) AS (VALUES (1,17), (2,17), (3,17), (4,17), (6,17), (5,17)),
1328   iter (id_key, row_type, link) AS (
1329       SELECT 0, 'base', 17
1330     UNION (
1331       WITH remaining(id_key, row_type, link, min) AS (
1332         SELECT tab.id_key, 'true'::text, iter.link, MIN(tab.id_key) OVER ()
1333         FROM tab INNER JOIN iter USING (link)
1334         WHERE tab.id_key > iter.id_key
1335       ),
1336       first_remaining AS (
1337         SELECT id_key, row_type, link
1338         FROM remaining
1339         WHERE id_key=min
1340       ),
1341       effect AS (
1342         SELECT tab.id_key, 'new'::text, tab.link
1343         FROM first_remaining e INNER JOIN tab ON e.id_key=tab.id_key
1344         WHERE e.row_type = 'false'
1345       )
1346       SELECT * FROM first_remaining
1347       UNION ALL SELECT * FROM effect
1348     )
1349   )
1350 SELECT * FROM iter;
1351  id_key | row_type | link 
1352 --------+----------+------
1353       0 | base     |   17
1354       1 | true     |   17
1355       2 | true     |   17
1356       3 | true     |   17
1357       4 | true     |   17
1358       5 | true     |   17
1359       6 | true     |   17
1360 (7 rows)
1361
1362 --
1363 -- Data-modifying statements in WITH
1364 --
1365 -- INSERT ... RETURNING
1366 WITH t AS (
1367     INSERT INTO y
1368     VALUES
1369         (11),
1370         (12),
1371         (13),
1372         (14),
1373         (15),
1374         (16),
1375         (17),
1376         (18),
1377         (19),
1378         (20)
1379     RETURNING *
1380 )
1381 SELECT * FROM t;
1382  a  
1383 ----
1384  11
1385  12
1386  13
1387  14
1388  15
1389  16
1390  17
1391  18
1392  19
1393  20
1394 (10 rows)
1395
1396 SELECT * FROM y;
1397  a  
1398 ----
1399   1
1400   2
1401   3
1402   4
1403   5
1404   6
1405   7
1406   8
1407   9
1408  10
1409  11
1410  12
1411  13
1412  14
1413  15
1414  16
1415  17
1416  18
1417  19
1418  20
1419 (20 rows)
1420
1421 -- UPDATE ... RETURNING
1422 WITH t AS (
1423     UPDATE y
1424     SET a=a+1
1425     RETURNING *
1426 )
1427 SELECT * FROM t;
1428  a  
1429 ----
1430   2
1431   3
1432   4
1433   5
1434   6
1435   7
1436   8
1437   9
1438  10
1439  11
1440  12
1441  13
1442  14
1443  15
1444  16
1445  17
1446  18
1447  19
1448  20
1449  21
1450 (20 rows)
1451
1452 SELECT * FROM y;
1453  a  
1454 ----
1455   2
1456   3
1457   4
1458   5
1459   6
1460   7
1461   8
1462   9
1463  10
1464  11
1465  12
1466  13
1467  14
1468  15
1469  16
1470  17
1471  18
1472  19
1473  20
1474  21
1475 (20 rows)
1476
1477 -- DELETE ... RETURNING
1478 WITH t AS (
1479     DELETE FROM y
1480     WHERE a <= 10
1481     RETURNING *
1482 )
1483 SELECT * FROM t;
1484  a  
1485 ----
1486   2
1487   3
1488   4
1489   5
1490   6
1491   7
1492   8
1493   9
1494  10
1495 (9 rows)
1496
1497 SELECT * FROM y;
1498  a  
1499 ----
1500  11
1501  12
1502  13
1503  14
1504  15
1505  16
1506  17
1507  18
1508  19
1509  20
1510  21
1511 (11 rows)
1512
1513 -- forward reference
1514 WITH RECURSIVE t AS (
1515         INSERT INTO y
1516                 SELECT a+5 FROM t2 WHERE a > 5
1517         RETURNING *
1518 ), t2 AS (
1519         UPDATE y SET a=a-11 RETURNING *
1520 )
1521 SELECT * FROM t
1522 UNION ALL
1523 SELECT * FROM t2;
1524  a  
1525 ----
1526  11
1527  12
1528  13
1529  14
1530  15
1531   0
1532   1
1533   2
1534   3
1535   4
1536   5
1537   6
1538   7
1539   8
1540   9
1541  10
1542 (16 rows)
1543
1544 SELECT * FROM y;
1545  a  
1546 ----
1547   0
1548   1
1549   2
1550   3
1551   4
1552   5
1553   6
1554  11
1555   7
1556  12
1557   8
1558  13
1559   9
1560  14
1561  10
1562  15
1563 (16 rows)
1564
1565 -- unconditional DO INSTEAD rule
1566 CREATE RULE y_rule AS ON DELETE TO y DO INSTEAD
1567   INSERT INTO y VALUES(42) RETURNING *;
1568 WITH t AS (
1569         DELETE FROM y RETURNING *
1570 )
1571 SELECT * FROM t;
1572  a  
1573 ----
1574  42
1575 (1 row)
1576
1577 SELECT * FROM y;
1578  a  
1579 ----
1580   0
1581   1
1582   2
1583   3
1584   4
1585   5
1586   6
1587  11
1588   7
1589  12
1590   8
1591  13
1592   9
1593  14
1594  10
1595  15
1596  42
1597 (17 rows)
1598
1599 DROP RULE y_rule ON y;
1600 -- check merging of outer CTE with CTE in a rule action
1601 CREATE TEMP TABLE bug6051 AS
1602   select i from generate_series(1,3) as t(i);
1603 SELECT * FROM bug6051;
1604  i 
1605 ---
1606  1
1607  2
1608  3
1609 (3 rows)
1610
1611 WITH t1 AS ( DELETE FROM bug6051 RETURNING * )
1612 INSERT INTO bug6051 SELECT * FROM t1;
1613 SELECT * FROM bug6051;
1614  i 
1615 ---
1616  1
1617  2
1618  3
1619 (3 rows)
1620
1621 CREATE TEMP TABLE bug6051_2 (i int);
1622 CREATE RULE bug6051_ins AS ON INSERT TO bug6051 DO INSTEAD
1623  INSERT INTO bug6051_2
1624  SELECT NEW.i;
1625 WITH t1 AS ( DELETE FROM bug6051 RETURNING * )
1626 INSERT INTO bug6051 SELECT * FROM t1;
1627 SELECT * FROM bug6051;
1628  i 
1629 ---
1630 (0 rows)
1631
1632 SELECT * FROM bug6051_2;
1633  i 
1634 ---
1635  1
1636  2
1637  3
1638 (3 rows)
1639
1640 -- a truly recursive CTE in the same list
1641 WITH RECURSIVE t(a) AS (
1642         SELECT 0
1643                 UNION ALL
1644         SELECT a+1 FROM t WHERE a+1 < 5
1645 ), t2 as (
1646         INSERT INTO y
1647                 SELECT * FROM t RETURNING *
1648 )
1649 SELECT * FROM t2 JOIN y USING (a) ORDER BY a;
1650  a 
1651 ---
1652  0
1653  1
1654  2
1655  3
1656  4
1657 (5 rows)
1658
1659 SELECT * FROM y;
1660  a  
1661 ----
1662   0
1663   1
1664   2
1665   3
1666   4
1667   5
1668   6
1669  11
1670   7
1671  12
1672   8
1673  13
1674   9
1675  14
1676  10
1677  15
1678  42
1679   0
1680   1
1681   2
1682   3
1683   4
1684 (22 rows)
1685
1686 -- data-modifying WITH in a modifying statement
1687 WITH t AS (
1688     DELETE FROM y
1689     WHERE a <= 10
1690     RETURNING *
1691 )
1692 INSERT INTO y SELECT -a FROM t RETURNING *;
1693   a  
1694 -----
1695    0
1696   -1
1697   -2
1698   -3
1699   -4
1700   -5
1701   -6
1702   -7
1703   -8
1704   -9
1705  -10
1706    0
1707   -1
1708   -2
1709   -3
1710   -4
1711 (16 rows)
1712
1713 SELECT * FROM y;
1714   a  
1715 -----
1716   11
1717   12
1718   13
1719   14
1720   15
1721   42
1722    0
1723   -1
1724   -2
1725   -3
1726   -4
1727   -5
1728   -6
1729   -7
1730   -8
1731   -9
1732  -10
1733    0
1734   -1
1735   -2
1736   -3
1737   -4
1738 (22 rows)
1739
1740 -- check that WITH query is run to completion even if outer query isn't
1741 WITH t AS (
1742     UPDATE y SET a = a * 100 RETURNING *
1743 )
1744 SELECT * FROM t LIMIT 10;
1745   a   
1746 ------
1747  1100
1748  1200
1749  1300
1750  1400
1751  1500
1752  4200
1753     0
1754  -100
1755  -200
1756  -300
1757 (10 rows)
1758
1759 SELECT * FROM y;
1760    a   
1761 -------
1762   1100
1763   1200
1764   1300
1765   1400
1766   1500
1767   4200
1768      0
1769   -100
1770   -200
1771   -300
1772   -400
1773   -500
1774   -600
1775   -700
1776   -800
1777   -900
1778  -1000
1779      0
1780   -100
1781   -200
1782   -300
1783   -400
1784 (22 rows)
1785
1786 -- check that run to completion happens in proper ordering
1787 TRUNCATE TABLE y;
1788 INSERT INTO y SELECT generate_series(1, 3);
1789 CREATE TEMPORARY TABLE yy (a INTEGER);
1790 WITH RECURSIVE t1 AS (
1791   INSERT INTO y SELECT * FROM y RETURNING *
1792 ), t2 AS (
1793   INSERT INTO yy SELECT * FROM t1 RETURNING *
1794 )
1795 SELECT 1;
1796  ?column? 
1797 ----------
1798         1
1799 (1 row)
1800
1801 SELECT * FROM y;
1802  a 
1803 ---
1804  1
1805  2
1806  3
1807  1
1808  2
1809  3
1810 (6 rows)
1811
1812 SELECT * FROM yy;
1813  a 
1814 ---
1815  1
1816  2
1817  3
1818 (3 rows)
1819
1820 WITH RECURSIVE t1 AS (
1821   INSERT INTO yy SELECT * FROM t2 RETURNING *
1822 ), t2 AS (
1823   INSERT INTO y SELECT * FROM y RETURNING *
1824 )
1825 SELECT 1;
1826  ?column? 
1827 ----------
1828         1
1829 (1 row)
1830
1831 SELECT * FROM y;
1832  a 
1833 ---
1834  1
1835  2
1836  3
1837  1
1838  2
1839  3
1840  1
1841  2
1842  3
1843  1
1844  2
1845  3
1846 (12 rows)
1847
1848 SELECT * FROM yy;
1849  a 
1850 ---
1851  1
1852  2
1853  3
1854  1
1855  2
1856  3
1857  1
1858  2
1859  3
1860 (9 rows)
1861
1862 -- triggers
1863 TRUNCATE TABLE y;
1864 INSERT INTO y SELECT generate_series(1, 10);
1865 CREATE FUNCTION y_trigger() RETURNS trigger AS $$
1866 begin
1867   raise notice 'y_trigger: a = %', new.a;
1868   return new;
1869 end;
1870 $$ LANGUAGE plpgsql;
1871 CREATE TRIGGER y_trig BEFORE INSERT ON y FOR EACH ROW
1872     EXECUTE PROCEDURE y_trigger();
1873 WITH t AS (
1874     INSERT INTO y
1875     VALUES
1876         (21),
1877         (22),
1878         (23)
1879     RETURNING *
1880 )
1881 SELECT * FROM t;
1882 NOTICE:  y_trigger: a = 21
1883 NOTICE:  y_trigger: a = 22
1884 NOTICE:  y_trigger: a = 23
1885  a  
1886 ----
1887  21
1888  22
1889  23
1890 (3 rows)
1891
1892 SELECT * FROM y;
1893  a  
1894 ----
1895   1
1896   2
1897   3
1898   4
1899   5
1900   6
1901   7
1902   8
1903   9
1904  10
1905  21
1906  22
1907  23
1908 (13 rows)
1909
1910 DROP TRIGGER y_trig ON y;
1911 CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH ROW
1912     EXECUTE PROCEDURE y_trigger();
1913 WITH t AS (
1914     INSERT INTO y
1915     VALUES
1916         (31),
1917         (32),
1918         (33)
1919     RETURNING *
1920 )
1921 SELECT * FROM t LIMIT 1;
1922 NOTICE:  y_trigger: a = 31
1923 NOTICE:  y_trigger: a = 32
1924 NOTICE:  y_trigger: a = 33
1925  a  
1926 ----
1927  31
1928 (1 row)
1929
1930 SELECT * FROM y;
1931  a  
1932 ----
1933   1
1934   2
1935   3
1936   4
1937   5
1938   6
1939   7
1940   8
1941   9
1942  10
1943  21
1944  22
1945  23
1946  31
1947  32
1948  33
1949 (16 rows)
1950
1951 DROP TRIGGER y_trig ON y;
1952 CREATE OR REPLACE FUNCTION y_trigger() RETURNS trigger AS $$
1953 begin
1954   raise notice 'y_trigger';
1955   return null;
1956 end;
1957 $$ LANGUAGE plpgsql;
1958 CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH STATEMENT
1959     EXECUTE PROCEDURE y_trigger();
1960 WITH t AS (
1961     INSERT INTO y
1962     VALUES
1963         (41),
1964         (42),
1965         (43)
1966     RETURNING *
1967 )
1968 SELECT * FROM t;
1969 NOTICE:  y_trigger
1970  a  
1971 ----
1972  41
1973  42
1974  43
1975 (3 rows)
1976
1977 SELECT * FROM y;
1978  a  
1979 ----
1980   1
1981   2
1982   3
1983   4
1984   5
1985   6
1986   7
1987   8
1988   9
1989  10
1990  21
1991  22
1992  23
1993  31
1994  32
1995  33
1996  41
1997  42
1998  43
1999 (19 rows)
2000
2001 DROP TRIGGER y_trig ON y;
2002 DROP FUNCTION y_trigger();
2003 -- WITH attached to inherited UPDATE or DELETE
2004 CREATE TEMP TABLE parent ( id int, val text );
2005 CREATE TEMP TABLE child1 ( ) INHERITS ( parent );
2006 CREATE TEMP TABLE child2 ( ) INHERITS ( parent );
2007 INSERT INTO parent VALUES ( 1, 'p1' );
2008 INSERT INTO child1 VALUES ( 11, 'c11' ),( 12, 'c12' );
2009 INSERT INTO child2 VALUES ( 23, 'c21' ),( 24, 'c22' );
2010 WITH rcte AS ( SELECT sum(id) AS totalid FROM parent )
2011 UPDATE parent SET id = id + totalid FROM rcte;
2012 SELECT * FROM parent;
2013  id | val 
2014 ----+-----
2015  72 | p1
2016  82 | c11
2017  83 | c12
2018  94 | c21
2019  95 | c22
2020 (5 rows)
2021
2022 WITH wcte AS ( INSERT INTO child1 VALUES ( 42, 'new' ) RETURNING id AS newid )
2023 UPDATE parent SET id = id + newid FROM wcte;
2024 SELECT * FROM parent;
2025  id  | val 
2026 -----+-----
2027  114 | p1
2028   42 | new
2029  124 | c11
2030  125 | c12
2031  136 | c21
2032  137 | c22
2033 (6 rows)
2034
2035 WITH rcte AS ( SELECT max(id) AS maxid FROM parent )
2036 DELETE FROM parent USING rcte WHERE id = maxid;
2037 SELECT * FROM parent;
2038  id  | val 
2039 -----+-----
2040  114 | p1
2041   42 | new
2042  124 | c11
2043  125 | c12
2044  136 | c21
2045 (5 rows)
2046
2047 WITH wcte AS ( INSERT INTO child2 VALUES ( 42, 'new2' ) RETURNING id AS newid )
2048 DELETE FROM parent USING wcte WHERE id = newid;
2049 SELECT * FROM parent;
2050  id  | val  
2051 -----+------
2052  114 | p1
2053  124 | c11
2054  125 | c12
2055  136 | c21
2056   42 | new2
2057 (5 rows)
2058
2059 -- check EXPLAIN VERBOSE for a wCTE with RETURNING
2060 EXPLAIN (VERBOSE, COSTS OFF)
2061 WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 )
2062 DELETE FROM a USING wcte WHERE aa = q2;
2063                    QUERY PLAN                   
2064 ------------------------------------------------
2065  Delete on public.a
2066    CTE wcte
2067      ->  Insert on public.int8_tbl
2068            Output: int8_tbl.q2
2069            ->  Result
2070                  Output: 42::bigint, 47::bigint
2071    ->  Nested Loop
2072          Output: a.ctid, wcte.*
2073          Join Filter: (a.aa = wcte.q2)
2074          ->  Seq Scan on public.a
2075                Output: a.ctid, a.aa
2076          ->  CTE Scan on wcte
2077                Output: wcte.*, wcte.q2
2078    ->  Nested Loop
2079          Output: b.ctid, wcte.*
2080          Join Filter: (b.aa = wcte.q2)
2081          ->  Seq Scan on public.b
2082                Output: b.ctid, b.aa
2083          ->  CTE Scan on wcte
2084                Output: wcte.*, wcte.q2
2085    ->  Nested Loop
2086          Output: c.ctid, wcte.*
2087          Join Filter: (c.aa = wcte.q2)
2088          ->  Seq Scan on public.c
2089                Output: c.ctid, c.aa
2090          ->  CTE Scan on wcte
2091                Output: wcte.*, wcte.q2
2092    ->  Nested Loop
2093          Output: d.ctid, wcte.*
2094          Join Filter: (d.aa = wcte.q2)
2095          ->  Seq Scan on public.d
2096                Output: d.ctid, d.aa
2097          ->  CTE Scan on wcte
2098                Output: wcte.*, wcte.q2
2099 (34 rows)
2100
2101 -- error cases
2102 -- data-modifying WITH tries to use its own output
2103 WITH RECURSIVE t AS (
2104         INSERT INTO y
2105                 SELECT * FROM t
2106 )
2107 VALUES(FALSE);
2108 ERROR:  recursive query "t" must not contain data-modifying statements
2109 LINE 1: WITH RECURSIVE t AS (
2110                        ^
2111 -- no RETURNING in a referenced data-modifying WITH
2112 WITH t AS (
2113         INSERT INTO y VALUES(0)
2114 )
2115 SELECT * FROM t;
2116 ERROR:  WITH query "t" does not have a RETURNING clause
2117 LINE 4: SELECT * FROM t;
2118                       ^
2119 -- data-modifying WITH allowed only at the top level
2120 SELECT * FROM (
2121         WITH t AS (UPDATE y SET a=a+1 RETURNING *)
2122         SELECT * FROM t
2123 ) ss;
2124 ERROR:  WITH clause containing a data-modifying statement must be at the top level
2125 LINE 2:  WITH t AS (UPDATE y SET a=a+1 RETURNING *)
2126               ^
2127 -- most variants of rules aren't allowed
2128 CREATE RULE y_rule AS ON INSERT TO y WHERE a=0 DO INSTEAD DELETE FROM y;
2129 WITH t AS (
2130         INSERT INTO y VALUES(0)
2131 )
2132 VALUES(FALSE);
2133 ERROR:  conditional DO INSTEAD rules are not supported for data-modifying statements in WITH
2134 DROP RULE y_rule ON y;