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