Consistently use "superuser" instead of "super user"
[pgsql.git] / src / test / regress / expected / with.out
blob3523a7dcc1608cad56f0b0068eab0496187ec979
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)
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)
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
31 SELECT sum(n) FROM t;
32  sum  
33 ------
34  5050
35 (1 row)
37 WITH RECURSIVE t(n) AS (
38     SELECT (VALUES(1))
39 UNION ALL
40     SELECT n+1 FROM t WHERE n < 5
42 SELECT * FROM t;
43  n 
44 ---
45  1
46  2
47  3
48  4
49  5
50 (5 rows)
52 -- UNION DISTINCT requires hashable type
53 WITH RECURSIVE t(n) AS (
54     VALUES (1::money)
55 UNION
56     SELECT n+1::money FROM t WHERE n < 100::money
58 SELECT sum(n) FROM t;
59 ERROR:  could not implement recursive UNION
60 DETAIL:  All column datatypes must be hashable.
61 -- recursive view
62 CREATE RECURSIVE VIEW nums (n) AS
63     VALUES (1)
64 UNION ALL
65     SELECT n+1 FROM nums WHERE n < 5;
66 SELECT * FROM nums;
67  n 
68 ---
69  1
70  2
71  3
72  4
73  5
74 (5 rows)
76 CREATE OR REPLACE RECURSIVE VIEW nums (n) AS
77     VALUES (1)
78 UNION ALL
79     SELECT n+1 FROM nums WHERE n < 6;
80 SELECT * FROM nums;
81  n 
82 ---
83  1
84  2
85  3
86  4
87  5
88  6
89 (6 rows)
91 -- This is an infinite loop with UNION ALL, but not with UNION
92 WITH RECURSIVE t(n) AS (
93     SELECT 1
94 UNION
95     SELECT 10-n FROM t)
96 SELECT * FROM t;
97  n 
98 ---
99  1
101 (2 rows)
103 -- This'd be an infinite loop, but outside query reads only as much as needed
104 WITH RECURSIVE t(n) AS (
105     VALUES (1)
106 UNION ALL
107     SELECT n+1 FROM t)
108 SELECT * FROM t LIMIT 10;
109  n  
110 ----
111   1
112   2
113   3
114   4
115   5
116   6
117   7
118   8
119   9
120  10
121 (10 rows)
123 -- UNION case should have same property
124 WITH RECURSIVE t(n) AS (
125     SELECT 1
126 UNION
127     SELECT n+1 FROM t)
128 SELECT * FROM t LIMIT 10;
129  n  
130 ----
131   1
132   2
133   3
134   4
135   5
136   6
137   7
138   8
139   9
140  10
141 (10 rows)
143 -- Test behavior with an unknown-type literal in the WITH
144 WITH q AS (SELECT 'foo' AS x)
145 SELECT x, pg_typeof(x) FROM q;
146   x  | pg_typeof 
147 -----+-----------
148  foo | text
149 (1 row)
151 WITH RECURSIVE t(n) AS (
152     SELECT 'foo'
153 UNION ALL
154     SELECT n || ' bar' FROM t WHERE length(n) < 20
156 SELECT n, pg_typeof(n) FROM t;
157             n            | pg_typeof 
158 -------------------------+-----------
159  foo                     | text
160  foo bar                 | text
161  foo bar bar             | text
162  foo bar bar bar         | text
163  foo bar bar bar bar     | text
164  foo bar bar bar bar bar | text
165 (6 rows)
167 -- In a perfect world, this would work and resolve the literal as int ...
168 -- but for now, we have to be content with resolving to text too soon.
169 WITH RECURSIVE t(n) AS (
170     SELECT '7'
171 UNION ALL
172     SELECT n+1 FROM t WHERE n < 10
174 SELECT n, pg_typeof(n) FROM t;
175 ERROR:  operator does not exist: text + integer
176 LINE 4:     SELECT n+1 FROM t WHERE n < 10
177                     ^
178 HINT:  No operator matches the given name and argument types. You might need to add explicit type casts.
179 -- Deeply nested WITH caused a list-munging problem in v13
180 -- Detection of cross-references and self-references
181 WITH RECURSIVE w1(c1) AS
182  (WITH w2(c2) AS
183   (WITH w3(c3) AS
184    (WITH w4(c4) AS
185     (WITH w5(c5) AS
186      (WITH RECURSIVE w6(c6) AS
187       (WITH w6(c6) AS
188        (WITH w8(c8) AS
189         (SELECT 1)
190         SELECT * FROM w8)
191        SELECT * FROM w6)
192       SELECT * FROM w6)
193      SELECT * FROM w5)
194     SELECT * FROM w4)
195    SELECT * FROM w3)
196   SELECT * FROM w2)
197 SELECT * FROM w1;
198  c1 
199 ----
200   1
201 (1 row)
203 -- Detection of invalid self-references
204 WITH RECURSIVE outermost(x) AS (
205  SELECT 1
206  UNION (WITH innermost1 AS (
207   SELECT 2
208   UNION (WITH innermost2 AS (
209    SELECT 3
210    UNION (WITH innermost3 AS (
211     SELECT 4
212     UNION (WITH innermost4 AS (
213      SELECT 5
214      UNION (WITH innermost5 AS (
215       SELECT 6
216       UNION (WITH innermost6 AS
217        (SELECT 7)
218        SELECT * FROM innermost6))
219       SELECT * FROM innermost5))
220      SELECT * FROM innermost4))
221     SELECT * FROM innermost3))
222    SELECT * FROM innermost2))
223   SELECT * FROM outermost
224   UNION SELECT * FROM innermost1)
226  SELECT * FROM outermost ORDER BY 1;
227  x 
236 (7 rows)
239 -- Some examples with a tree
241 -- department structure represented here is as follows:
243 -- ROOT-+->A-+->B-+->C
244 --      |         |
245 --      |         +->D-+->F
246 --      +->E-+->G
247 CREATE TEMP TABLE department (
248         id INTEGER PRIMARY KEY,  -- department ID
249         parent_department INTEGER REFERENCES department, -- upper department ID
250         name TEXT -- department name
252 INSERT INTO department VALUES (0, NULL, 'ROOT');
253 INSERT INTO department VALUES (1, 0, 'A');
254 INSERT INTO department VALUES (2, 1, 'B');
255 INSERT INTO department VALUES (3, 2, 'C');
256 INSERT INTO department VALUES (4, 2, 'D');
257 INSERT INTO department VALUES (5, 0, 'E');
258 INSERT INTO department VALUES (6, 4, 'F');
259 INSERT INTO department VALUES (7, 5, 'G');
260 -- extract all departments under 'A'. Result should be A, B, C, D and F
261 WITH RECURSIVE subdepartment AS
263         -- non recursive term
264         SELECT name as root_name, * FROM department WHERE name = 'A'
265         UNION ALL
266         -- recursive term
267         SELECT sd.root_name, d.* FROM department AS d, subdepartment AS sd
268                 WHERE d.parent_department = sd.id
270 SELECT * FROM subdepartment ORDER BY name;
271  root_name | id | parent_department | name 
272 -----------+----+-------------------+------
273  A         |  1 |                 0 | A
274  A         |  2 |                 1 | B
275  A         |  3 |                 2 | C
276  A         |  4 |                 2 | D
277  A         |  6 |                 4 | F
278 (5 rows)
280 -- extract all departments under 'A' with "level" number
281 WITH RECURSIVE subdepartment(level, id, parent_department, name) AS
283         -- non recursive term
284         SELECT 1, * FROM department WHERE name = 'A'
285         UNION ALL
286         -- recursive term
287         SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd
288                 WHERE d.parent_department = sd.id
290 SELECT * FROM subdepartment ORDER BY name;
291  level | id | parent_department | name 
292 -------+----+-------------------+------
293      1 |  1 |                 0 | A
294      2 |  2 |                 1 | B
295      3 |  3 |                 2 | C
296      3 |  4 |                 2 | D
297      4 |  6 |                 4 | F
298 (5 rows)
300 -- extract all departments under 'A' with "level" number.
301 -- Only shows level 2 or more
302 WITH RECURSIVE subdepartment(level, id, parent_department, name) AS
304         -- non recursive term
305         SELECT 1, * FROM department WHERE name = 'A'
306         UNION ALL
307         -- recursive term
308         SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd
309                 WHERE d.parent_department = sd.id
311 SELECT * FROM subdepartment WHERE level >= 2 ORDER BY name;
312  level | id | parent_department | name 
313 -------+----+-------------------+------
314      2 |  2 |                 1 | B
315      3 |  3 |                 2 | C
316      3 |  4 |                 2 | D
317      4 |  6 |                 4 | F
318 (4 rows)
320 -- "RECURSIVE" is ignored if the query has no self-reference
321 WITH RECURSIVE subdepartment AS
323         -- note lack of recursive UNION structure
324         SELECT * FROM department WHERE name = 'A'
326 SELECT * FROM subdepartment ORDER BY name;
327  id | parent_department | name 
328 ----+-------------------+------
329   1 |                 0 | A
330 (1 row)
332 -- inside subqueries
333 SELECT count(*) FROM (
334     WITH RECURSIVE t(n) AS (
335         SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 500
336     )
337     SELECT * FROM t) AS t WHERE n < (
338         SELECT count(*) FROM (
339             WITH RECURSIVE t(n) AS (
340                    SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 100
341                 )
342             SELECT * FROM t WHERE n < 50000
343          ) AS t WHERE n < 100);
344  count 
345 -------
346     98
347 (1 row)
349 -- use same CTE twice at different subquery levels
350 WITH q1(x,y) AS (
351     SELECT hundred, sum(ten) FROM tenk1 GROUP BY hundred
352   )
353 SELECT count(*) FROM q1 WHERE y > (SELECT sum(y)/100 FROM q1 qsub);
354  count 
355 -------
356     50
357 (1 row)
359 -- via a VIEW
360 CREATE TEMPORARY VIEW vsubdepartment AS
361         WITH RECURSIVE subdepartment AS
362         (
363                  -- non recursive term
364                 SELECT * FROM department WHERE name = 'A'
365                 UNION ALL
366                 -- recursive term
367                 SELECT d.* FROM department AS d, subdepartment AS sd
368                         WHERE d.parent_department = sd.id
369         )
370         SELECT * FROM subdepartment;
371 SELECT * FROM vsubdepartment ORDER BY name;
372  id | parent_department | name 
373 ----+-------------------+------
374   1 |                 0 | A
375   2 |                 1 | B
376   3 |                 2 | C
377   4 |                 2 | D
378   6 |                 4 | F
379 (5 rows)
381 -- Check reverse listing
382 SELECT pg_get_viewdef('vsubdepartment'::regclass);
383                 pg_get_viewdef                 
384 -----------------------------------------------
385   WITH RECURSIVE subdepartment AS (           +
386           SELECT department.id,               +
387              department.parent_department,    +
388              department.name                  +
389             FROM department                   +
390            WHERE (department.name = 'A'::text)+
391          UNION ALL                            +
392           SELECT d.id,                        +
393              d.parent_department,             +
394              d.name                           +
395             FROM department d,                +
396              subdepartment sd                 +
397            WHERE (d.parent_department = sd.id)+
398          )                                    +
399   SELECT subdepartment.id,                    +
400      subdepartment.parent_department,         +
401      subdepartment.name                       +
402     FROM subdepartment;
403 (1 row)
405 SELECT pg_get_viewdef('vsubdepartment'::regclass, true);
406                pg_get_viewdef                
407 ---------------------------------------------
408   WITH RECURSIVE subdepartment AS (         +
409           SELECT department.id,             +
410              department.parent_department,  +
411              department.name                +
412             FROM department                 +
413            WHERE department.name = 'A'::text+
414          UNION ALL                          +
415           SELECT d.id,                      +
416              d.parent_department,           +
417              d.name                         +
418             FROM department d,              +
419              subdepartment sd               +
420            WHERE d.parent_department = sd.id+
421          )                                  +
422   SELECT subdepartment.id,                  +
423      subdepartment.parent_department,       +
424      subdepartment.name                     +
425     FROM subdepartment;
426 (1 row)
428 -- Another reverse-listing example
429 CREATE VIEW sums_1_100 AS
430 WITH RECURSIVE t(n) AS (
431     VALUES (1)
432 UNION ALL
433     SELECT n+1 FROM t WHERE n < 100
435 SELECT sum(n) FROM t;
436 \d+ sums_1_100
437                          View "public.sums_1_100"
438  Column |  Type  | Collation | Nullable | Default | Storage | Description 
439 --------+--------+-----------+----------+---------+---------+-------------
440  sum    | bigint |           |          |         | plain   | 
441 View definition:
442  WITH RECURSIVE t(n) AS (
443          VALUES (1)
444         UNION ALL
445          SELECT t_1.n + 1
446            FROM t t_1
447           WHERE t_1.n < 100
448         )
449  SELECT sum(t.n) AS sum
450    FROM t;
452 -- corner case in which sub-WITH gets initialized first
453 with recursive q as (
454       select * from department
455     union all
456       (with x as (select * from q)
457        select * from x)
458     )
459 select * from q limit 24;
460  id | parent_department | name 
461 ----+-------------------+------
462   0 |                   | ROOT
463   1 |                 0 | A
464   2 |                 1 | B
465   3 |                 2 | C
466   4 |                 2 | D
467   5 |                 0 | E
468   6 |                 4 | F
469   7 |                 5 | G
470   0 |                   | ROOT
471   1 |                 0 | A
472   2 |                 1 | B
473   3 |                 2 | C
474   4 |                 2 | D
475   5 |                 0 | E
476   6 |                 4 | F
477   7 |                 5 | G
478   0 |                   | ROOT
479   1 |                 0 | A
480   2 |                 1 | B
481   3 |                 2 | C
482   4 |                 2 | D
483   5 |                 0 | E
484   6 |                 4 | F
485   7 |                 5 | G
486 (24 rows)
488 with recursive q as (
489       select * from department
490     union all
491       (with recursive x as (
492            select * from department
493          union all
494            (select * from q union all select * from x)
495         )
496        select * from x)
497     )
498 select * from q limit 32;
499  id | parent_department | name 
500 ----+-------------------+------
501   0 |                   | ROOT
502   1 |                 0 | A
503   2 |                 1 | B
504   3 |                 2 | C
505   4 |                 2 | D
506   5 |                 0 | E
507   6 |                 4 | F
508   7 |                 5 | G
509   0 |                   | ROOT
510   1 |                 0 | A
511   2 |                 1 | B
512   3 |                 2 | C
513   4 |                 2 | D
514   5 |                 0 | E
515   6 |                 4 | F
516   7 |                 5 | G
517   0 |                   | ROOT
518   1 |                 0 | A
519   2 |                 1 | B
520   3 |                 2 | C
521   4 |                 2 | D
522   5 |                 0 | E
523   6 |                 4 | F
524   7 |                 5 | G
525   0 |                   | ROOT
526   1 |                 0 | A
527   2 |                 1 | B
528   3 |                 2 | C
529   4 |                 2 | D
530   5 |                 0 | E
531   6 |                 4 | F
532   7 |                 5 | G
533 (32 rows)
535 -- recursive term has sub-UNION
536 WITH RECURSIVE t(i,j) AS (
537         VALUES (1,2)
538         UNION ALL
539         SELECT t2.i, t.j+1 FROM
540                 (SELECT 2 AS i UNION ALL SELECT 3 AS i) AS t2
541                 JOIN t ON (t2.i = t.i+1))
542         SELECT * FROM t;
543  i | j 
544 ---+---
545  1 | 2
546  2 | 3
547  3 | 4
548 (3 rows)
551 -- different tree example
553 CREATE TEMPORARY TABLE tree(
554     id INTEGER PRIMARY KEY,
555     parent_id INTEGER REFERENCES tree(id)
557 INSERT INTO tree
558 VALUES (1, NULL), (2, 1), (3,1), (4,2), (5,2), (6,2), (7,3), (8,3),
559        (9,4), (10,4), (11,7), (12,7), (13,7), (14, 9), (15,11), (16,11);
561 -- get all paths from "second level" nodes to leaf nodes
563 WITH RECURSIVE t(id, path) AS (
564     VALUES(1,ARRAY[]::integer[])
565 UNION ALL
566     SELECT tree.id, t.path || tree.id
567     FROM tree JOIN t ON (tree.parent_id = t.id)
569 SELECT t1.*, t2.* FROM t AS t1 JOIN t AS t2 ON
570         (t1.path[1] = t2.path[1] AND
571         array_upper(t1.path,1) = 1 AND
572         array_upper(t2.path,1) > 1)
573         ORDER BY t1.id, t2.id;
574  id | path | id |    path     
575 ----+------+----+-------------
576   2 | {2}  |  4 | {2,4}
577   2 | {2}  |  5 | {2,5}
578   2 | {2}  |  6 | {2,6}
579   2 | {2}  |  9 | {2,4,9}
580   2 | {2}  | 10 | {2,4,10}
581   2 | {2}  | 14 | {2,4,9,14}
582   3 | {3}  |  7 | {3,7}
583   3 | {3}  |  8 | {3,8}
584   3 | {3}  | 11 | {3,7,11}
585   3 | {3}  | 12 | {3,7,12}
586   3 | {3}  | 13 | {3,7,13}
587   3 | {3}  | 15 | {3,7,11,15}
588   3 | {3}  | 16 | {3,7,11,16}
589 (13 rows)
591 -- just count 'em
592 WITH RECURSIVE t(id, path) AS (
593     VALUES(1,ARRAY[]::integer[])
594 UNION ALL
595     SELECT tree.id, t.path || tree.id
596     FROM tree JOIN t ON (tree.parent_id = t.id)
598 SELECT t1.id, count(t2.*) FROM t AS t1 JOIN t AS t2 ON
599         (t1.path[1] = t2.path[1] AND
600         array_upper(t1.path,1) = 1 AND
601         array_upper(t2.path,1) > 1)
602         GROUP BY t1.id
603         ORDER BY t1.id;
604  id | count 
605 ----+-------
606   2 |     6
607   3 |     7
608 (2 rows)
610 -- this variant tickled a whole-row-variable bug in 8.4devel
611 WITH RECURSIVE t(id, path) AS (
612     VALUES(1,ARRAY[]::integer[])
613 UNION ALL
614     SELECT tree.id, t.path || tree.id
615     FROM tree JOIN t ON (tree.parent_id = t.id)
617 SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON
618 (t1.id=t2.id);
619  id |    path     |         t2         
620 ----+-------------+--------------------
621   1 | {}          | (1,{})
622   2 | {2}         | (2,{2})
623   3 | {3}         | (3,{3})
624   4 | {2,4}       | (4,"{2,4}")
625   5 | {2,5}       | (5,"{2,5}")
626   6 | {2,6}       | (6,"{2,6}")
627   7 | {3,7}       | (7,"{3,7}")
628   8 | {3,8}       | (8,"{3,8}")
629   9 | {2,4,9}     | (9,"{2,4,9}")
630  10 | {2,4,10}    | (10,"{2,4,10}")
631  11 | {3,7,11}    | (11,"{3,7,11}")
632  12 | {3,7,12}    | (12,"{3,7,12}")
633  13 | {3,7,13}    | (13,"{3,7,13}")
634  14 | {2,4,9,14}  | (14,"{2,4,9,14}")
635  15 | {3,7,11,15} | (15,"{3,7,11,15}")
636  16 | {3,7,11,16} | (16,"{3,7,11,16}")
637 (16 rows)
639 -- SEARCH clause
640 create temp table graph0( f int, t int, label text );
641 insert into graph0 values
642         (1, 2, 'arc 1 -> 2'),
643         (1, 3, 'arc 1 -> 3'),
644         (2, 3, 'arc 2 -> 3'),
645         (1, 4, 'arc 1 -> 4'),
646         (4, 5, 'arc 4 -> 5');
647 with recursive search_graph(f, t, label) as (
648         select * from graph0 g
649         union all
650         select g.*
651         from graph0 g, search_graph sg
652         where g.f = sg.t
653 ) search depth first by f, t set seq
654 select * from search_graph order by seq;
655  f | t |   label    |        seq        
656 ---+---+------------+-------------------
657  1 | 2 | arc 1 -> 2 | {"(1,2)"}
658  2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}
659  1 | 3 | arc 1 -> 3 | {"(1,3)"}
660  1 | 4 | arc 1 -> 4 | {"(1,4)"}
661  4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}
662  2 | 3 | arc 2 -> 3 | {"(2,3)"}
663  4 | 5 | arc 4 -> 5 | {"(4,5)"}
664 (7 rows)
666 with recursive search_graph(f, t, label) as (
667         select * from graph0 g
668         union distinct
669         select g.*
670         from graph0 g, search_graph sg
671         where g.f = sg.t
672 ) search depth first by f, t set seq
673 select * from search_graph order by seq;
674  f | t |   label    |        seq        
675 ---+---+------------+-------------------
676  1 | 2 | arc 1 -> 2 | {"(1,2)"}
677  2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}
678  1 | 3 | arc 1 -> 3 | {"(1,3)"}
679  1 | 4 | arc 1 -> 4 | {"(1,4)"}
680  4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}
681  2 | 3 | arc 2 -> 3 | {"(2,3)"}
682  4 | 5 | arc 4 -> 5 | {"(4,5)"}
683 (7 rows)
685 with recursive search_graph(f, t, label) as (
686         select * from graph0 g
687         union all
688         select g.*
689         from graph0 g, search_graph sg
690         where g.f = sg.t
691 ) search breadth first by f, t set seq
692 select * from search_graph order by seq;
693  f | t |   label    |   seq   
694 ---+---+------------+---------
695  1 | 2 | arc 1 -> 2 | (0,1,2)
696  1 | 3 | arc 1 -> 3 | (0,1,3)
697  1 | 4 | arc 1 -> 4 | (0,1,4)
698  2 | 3 | arc 2 -> 3 | (0,2,3)
699  4 | 5 | arc 4 -> 5 | (0,4,5)
700  2 | 3 | arc 2 -> 3 | (1,2,3)
701  4 | 5 | arc 4 -> 5 | (1,4,5)
702 (7 rows)
704 with recursive search_graph(f, t, label) as (
705         select * from graph0 g
706         union distinct
707         select g.*
708         from graph0 g, search_graph sg
709         where g.f = sg.t
710 ) search breadth first by f, t set seq
711 select * from search_graph order by seq;
712  f | t |   label    |   seq   
713 ---+---+------------+---------
714  1 | 2 | arc 1 -> 2 | (0,1,2)
715  1 | 3 | arc 1 -> 3 | (0,1,3)
716  1 | 4 | arc 1 -> 4 | (0,1,4)
717  2 | 3 | arc 2 -> 3 | (0,2,3)
718  4 | 5 | arc 4 -> 5 | (0,4,5)
719  2 | 3 | arc 2 -> 3 | (1,2,3)
720  4 | 5 | arc 4 -> 5 | (1,4,5)
721 (7 rows)
723 -- various syntax errors
724 with recursive search_graph(f, t, label) as (
725         select * from graph0 g
726         union all
727         select g.*
728         from graph0 g, search_graph sg
729         where g.f = sg.t
730 ) search depth first by foo, tar set seq
731 select * from search_graph;
732 ERROR:  search column "foo" not in WITH query column list
733 LINE 7: ) search depth first by foo, tar set seq
734           ^
735 with recursive search_graph(f, t, label) as (
736         select * from graph0 g
737         union all
738         select g.*
739         from graph0 g, search_graph sg
740         where g.f = sg.t
741 ) search depth first by f, t set label
742 select * from search_graph;
743 ERROR:  search sequence column name "label" already used in WITH query column list
744 LINE 7: ) search depth first by f, t set label
745           ^
746 with recursive search_graph(f, t, label) as (
747         select * from graph0 g
748         union all
749         select g.*
750         from graph0 g, search_graph sg
751         where g.f = sg.t
752 ) search depth first by f, t, f set seq
753 select * from search_graph;
754 ERROR:  search column "f" specified more than once
755 LINE 7: ) search depth first by f, t, f set seq
756           ^
757 with recursive search_graph(f, t, label) as (
758         select * from graph0 g
759         union all
760         select * from graph0 g
761         union all
762         select g.*
763         from graph0 g, search_graph sg
764         where g.f = sg.t
765 ) search depth first by f, t set seq
766 select * from search_graph order by seq;
767 ERROR:  with a SEARCH or CYCLE clause, the left side of the UNION must be a SELECT
768 with recursive search_graph(f, t, label) as (
769         select * from graph0 g
770         union all
771         (select * from graph0 g
772         union all
773         select g.*
774         from graph0 g, search_graph sg
775         where g.f = sg.t)
776 ) search depth first by f, t set seq
777 select * from search_graph order by seq;
778 ERROR:  with a SEARCH or CYCLE clause, the right side of the UNION must be a SELECT
779 -- test ruleutils and view expansion
780 create temp view v_search as
781 with recursive search_graph(f, t, label) as (
782         select * from graph0 g
783         union all
784         select g.*
785         from graph0 g, search_graph sg
786         where g.f = sg.t
787 ) search depth first by f, t set seq
788 select f, t, label from search_graph;
789 select pg_get_viewdef('v_search');
790                  pg_get_viewdef                 
791 ------------------------------------------------
792   WITH RECURSIVE search_graph(f, t, label) AS (+
793           SELECT g.f,                          +
794              g.t,                              +
795              g.label                           +
796             FROM graph0 g                      +
797          UNION ALL                             +
798           SELECT g.f,                          +
799              g.t,                              +
800              g.label                           +
801             FROM graph0 g,                     +
802              search_graph sg                   +
803            WHERE (g.f = sg.t)                  +
804          ) SEARCH DEPTH FIRST BY f, t SET seq  +
805   SELECT search_graph.f,                       +
806      search_graph.t,                           +
807      search_graph.label                        +
808     FROM search_graph;
809 (1 row)
811 select * from v_search;
812  f | t |   label    
813 ---+---+------------
814  1 | 2 | arc 1 -> 2
815  1 | 3 | arc 1 -> 3
816  2 | 3 | arc 2 -> 3
817  1 | 4 | arc 1 -> 4
818  4 | 5 | arc 4 -> 5
819  2 | 3 | arc 2 -> 3
820  4 | 5 | arc 4 -> 5
821 (7 rows)
824 -- test cycle detection
826 create temp table graph( f int, t int, label text );
827 insert into graph values
828         (1, 2, 'arc 1 -> 2'),
829         (1, 3, 'arc 1 -> 3'),
830         (2, 3, 'arc 2 -> 3'),
831         (1, 4, 'arc 1 -> 4'),
832         (4, 5, 'arc 4 -> 5'),
833         (5, 1, 'arc 5 -> 1');
834 with recursive search_graph(f, t, label, is_cycle, path) as (
835         select *, false, array[row(g.f, g.t)] from graph g
836         union all
837         select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
838         from graph g, search_graph sg
839         where g.f = sg.t and not is_cycle
841 select * from search_graph;
842  f | t |   label    | is_cycle |                   path                    
843 ---+---+------------+----------+-------------------------------------------
844  1 | 2 | arc 1 -> 2 | f        | {"(1,2)"}
845  1 | 3 | arc 1 -> 3 | f        | {"(1,3)"}
846  2 | 3 | arc 2 -> 3 | f        | {"(2,3)"}
847  1 | 4 | arc 1 -> 4 | f        | {"(1,4)"}
848  4 | 5 | arc 4 -> 5 | f        | {"(4,5)"}
849  5 | 1 | arc 5 -> 1 | f        | {"(5,1)"}
850  1 | 2 | arc 1 -> 2 | f        | {"(5,1)","(1,2)"}
851  1 | 3 | arc 1 -> 3 | f        | {"(5,1)","(1,3)"}
852  1 | 4 | arc 1 -> 4 | f        | {"(5,1)","(1,4)"}
853  2 | 3 | arc 2 -> 3 | f        | {"(1,2)","(2,3)"}
854  4 | 5 | arc 4 -> 5 | f        | {"(1,4)","(4,5)"}
855  5 | 1 | arc 5 -> 1 | f        | {"(4,5)","(5,1)"}
856  1 | 2 | arc 1 -> 2 | f        | {"(4,5)","(5,1)","(1,2)"}
857  1 | 3 | arc 1 -> 3 | f        | {"(4,5)","(5,1)","(1,3)"}
858  1 | 4 | arc 1 -> 4 | f        | {"(4,5)","(5,1)","(1,4)"}
859  2 | 3 | arc 2 -> 3 | f        | {"(5,1)","(1,2)","(2,3)"}
860  4 | 5 | arc 4 -> 5 | f        | {"(5,1)","(1,4)","(4,5)"}
861  5 | 1 | arc 5 -> 1 | f        | {"(1,4)","(4,5)","(5,1)"}
862  1 | 2 | arc 1 -> 2 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
863  1 | 3 | arc 1 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
864  1 | 4 | arc 1 -> 4 | t        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
865  2 | 3 | arc 2 -> 3 | f        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
866  4 | 5 | arc 4 -> 5 | t        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
867  5 | 1 | arc 5 -> 1 | t        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
868  2 | 3 | arc 2 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
869 (25 rows)
871 -- UNION DISTINCT exercises row type hashing support
872 with recursive search_graph(f, t, label, is_cycle, path) as (
873         select *, false, array[row(g.f, g.t)] from graph g
874         union distinct
875         select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
876         from graph g, search_graph sg
877         where g.f = sg.t and not is_cycle
879 select * from search_graph;
880  f | t |   label    | is_cycle |                   path                    
881 ---+---+------------+----------+-------------------------------------------
882  1 | 2 | arc 1 -> 2 | f        | {"(1,2)"}
883  1 | 3 | arc 1 -> 3 | f        | {"(1,3)"}
884  2 | 3 | arc 2 -> 3 | f        | {"(2,3)"}
885  1 | 4 | arc 1 -> 4 | f        | {"(1,4)"}
886  4 | 5 | arc 4 -> 5 | f        | {"(4,5)"}
887  5 | 1 | arc 5 -> 1 | f        | {"(5,1)"}
888  1 | 2 | arc 1 -> 2 | f        | {"(5,1)","(1,2)"}
889  1 | 3 | arc 1 -> 3 | f        | {"(5,1)","(1,3)"}
890  1 | 4 | arc 1 -> 4 | f        | {"(5,1)","(1,4)"}
891  2 | 3 | arc 2 -> 3 | f        | {"(1,2)","(2,3)"}
892  4 | 5 | arc 4 -> 5 | f        | {"(1,4)","(4,5)"}
893  5 | 1 | arc 5 -> 1 | f        | {"(4,5)","(5,1)"}
894  1 | 2 | arc 1 -> 2 | f        | {"(4,5)","(5,1)","(1,2)"}
895  1 | 3 | arc 1 -> 3 | f        | {"(4,5)","(5,1)","(1,3)"}
896  1 | 4 | arc 1 -> 4 | f        | {"(4,5)","(5,1)","(1,4)"}
897  2 | 3 | arc 2 -> 3 | f        | {"(5,1)","(1,2)","(2,3)"}
898  4 | 5 | arc 4 -> 5 | f        | {"(5,1)","(1,4)","(4,5)"}
899  5 | 1 | arc 5 -> 1 | f        | {"(1,4)","(4,5)","(5,1)"}
900  1 | 2 | arc 1 -> 2 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
901  1 | 3 | arc 1 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
902  1 | 4 | arc 1 -> 4 | t        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
903  2 | 3 | arc 2 -> 3 | f        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
904  4 | 5 | arc 4 -> 5 | t        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
905  5 | 1 | arc 5 -> 1 | t        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
906  2 | 3 | arc 2 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
907 (25 rows)
909 -- ordering by the path column has same effect as SEARCH DEPTH FIRST
910 with recursive search_graph(f, t, label, is_cycle, path) as (
911         select *, false, array[row(g.f, g.t)] from graph g
912         union all
913         select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
914         from graph g, search_graph sg
915         where g.f = sg.t and not is_cycle
917 select * from search_graph order by path;
918  f | t |   label    | is_cycle |                   path                    
919 ---+---+------------+----------+-------------------------------------------
920  1 | 2 | arc 1 -> 2 | f        | {"(1,2)"}
921  2 | 3 | arc 2 -> 3 | f        | {"(1,2)","(2,3)"}
922  1 | 3 | arc 1 -> 3 | f        | {"(1,3)"}
923  1 | 4 | arc 1 -> 4 | f        | {"(1,4)"}
924  4 | 5 | arc 4 -> 5 | f        | {"(1,4)","(4,5)"}
925  5 | 1 | arc 5 -> 1 | f        | {"(1,4)","(4,5)","(5,1)"}
926  1 | 2 | arc 1 -> 2 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
927  2 | 3 | arc 2 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
928  1 | 3 | arc 1 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
929  1 | 4 | arc 1 -> 4 | t        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
930  2 | 3 | arc 2 -> 3 | f        | {"(2,3)"}
931  4 | 5 | arc 4 -> 5 | f        | {"(4,5)"}
932  5 | 1 | arc 5 -> 1 | f        | {"(4,5)","(5,1)"}
933  1 | 2 | arc 1 -> 2 | f        | {"(4,5)","(5,1)","(1,2)"}
934  2 | 3 | arc 2 -> 3 | f        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
935  1 | 3 | arc 1 -> 3 | f        | {"(4,5)","(5,1)","(1,3)"}
936  1 | 4 | arc 1 -> 4 | f        | {"(4,5)","(5,1)","(1,4)"}
937  4 | 5 | arc 4 -> 5 | t        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
938  5 | 1 | arc 5 -> 1 | f        | {"(5,1)"}
939  1 | 2 | arc 1 -> 2 | f        | {"(5,1)","(1,2)"}
940  2 | 3 | arc 2 -> 3 | f        | {"(5,1)","(1,2)","(2,3)"}
941  1 | 3 | arc 1 -> 3 | f        | {"(5,1)","(1,3)"}
942  1 | 4 | arc 1 -> 4 | f        | {"(5,1)","(1,4)"}
943  4 | 5 | arc 4 -> 5 | f        | {"(5,1)","(1,4)","(4,5)"}
944  5 | 1 | arc 5 -> 1 | t        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
945 (25 rows)
947 -- CYCLE clause
948 with recursive search_graph(f, t, label) as (
949         select * from graph g
950         union all
951         select g.*
952         from graph g, search_graph sg
953         where g.f = sg.t
954 ) cycle f, t set is_cycle using path
955 select * from search_graph;
956  f | t |   label    | is_cycle |                   path                    
957 ---+---+------------+----------+-------------------------------------------
958  1 | 2 | arc 1 -> 2 | f        | {"(1,2)"}
959  1 | 3 | arc 1 -> 3 | f        | {"(1,3)"}
960  2 | 3 | arc 2 -> 3 | f        | {"(2,3)"}
961  1 | 4 | arc 1 -> 4 | f        | {"(1,4)"}
962  4 | 5 | arc 4 -> 5 | f        | {"(4,5)"}
963  5 | 1 | arc 5 -> 1 | f        | {"(5,1)"}
964  1 | 2 | arc 1 -> 2 | f        | {"(5,1)","(1,2)"}
965  1 | 3 | arc 1 -> 3 | f        | {"(5,1)","(1,3)"}
966  1 | 4 | arc 1 -> 4 | f        | {"(5,1)","(1,4)"}
967  2 | 3 | arc 2 -> 3 | f        | {"(1,2)","(2,3)"}
968  4 | 5 | arc 4 -> 5 | f        | {"(1,4)","(4,5)"}
969  5 | 1 | arc 5 -> 1 | f        | {"(4,5)","(5,1)"}
970  1 | 2 | arc 1 -> 2 | f        | {"(4,5)","(5,1)","(1,2)"}
971  1 | 3 | arc 1 -> 3 | f        | {"(4,5)","(5,1)","(1,3)"}
972  1 | 4 | arc 1 -> 4 | f        | {"(4,5)","(5,1)","(1,4)"}
973  2 | 3 | arc 2 -> 3 | f        | {"(5,1)","(1,2)","(2,3)"}
974  4 | 5 | arc 4 -> 5 | f        | {"(5,1)","(1,4)","(4,5)"}
975  5 | 1 | arc 5 -> 1 | f        | {"(1,4)","(4,5)","(5,1)"}
976  1 | 2 | arc 1 -> 2 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
977  1 | 3 | arc 1 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
978  1 | 4 | arc 1 -> 4 | t        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
979  2 | 3 | arc 2 -> 3 | f        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
980  4 | 5 | arc 4 -> 5 | t        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
981  5 | 1 | arc 5 -> 1 | t        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
982  2 | 3 | arc 2 -> 3 | f        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
983 (25 rows)
985 with recursive search_graph(f, t, label) as (
986         select * from graph g
987         union distinct
988         select g.*
989         from graph g, search_graph sg
990         where g.f = sg.t
991 ) cycle f, t set is_cycle to 'Y' default 'N' using path
992 select * from search_graph;
993  f | t |   label    | is_cycle |                   path                    
994 ---+---+------------+----------+-------------------------------------------
995  1 | 2 | arc 1 -> 2 | N        | {"(1,2)"}
996  1 | 3 | arc 1 -> 3 | N        | {"(1,3)"}
997  2 | 3 | arc 2 -> 3 | N        | {"(2,3)"}
998  1 | 4 | arc 1 -> 4 | N        | {"(1,4)"}
999  4 | 5 | arc 4 -> 5 | N        | {"(4,5)"}
1000  5 | 1 | arc 5 -> 1 | N        | {"(5,1)"}
1001  1 | 2 | arc 1 -> 2 | N        | {"(5,1)","(1,2)"}
1002  1 | 3 | arc 1 -> 3 | N        | {"(5,1)","(1,3)"}
1003  1 | 4 | arc 1 -> 4 | N        | {"(5,1)","(1,4)"}
1004  2 | 3 | arc 2 -> 3 | N        | {"(1,2)","(2,3)"}
1005  4 | 5 | arc 4 -> 5 | N        | {"(1,4)","(4,5)"}
1006  5 | 1 | arc 5 -> 1 | N        | {"(4,5)","(5,1)"}
1007  1 | 2 | arc 1 -> 2 | N        | {"(4,5)","(5,1)","(1,2)"}
1008  1 | 3 | arc 1 -> 3 | N        | {"(4,5)","(5,1)","(1,3)"}
1009  1 | 4 | arc 1 -> 4 | N        | {"(4,5)","(5,1)","(1,4)"}
1010  2 | 3 | arc 2 -> 3 | N        | {"(5,1)","(1,2)","(2,3)"}
1011  4 | 5 | arc 4 -> 5 | N        | {"(5,1)","(1,4)","(4,5)"}
1012  5 | 1 | arc 5 -> 1 | N        | {"(1,4)","(4,5)","(5,1)"}
1013  1 | 2 | arc 1 -> 2 | N        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
1014  1 | 3 | arc 1 -> 3 | N        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
1015  1 | 4 | arc 1 -> 4 | Y        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
1016  2 | 3 | arc 2 -> 3 | N        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
1017  4 | 5 | arc 4 -> 5 | Y        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
1018  5 | 1 | arc 5 -> 1 | Y        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
1019  2 | 3 | arc 2 -> 3 | N        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
1020 (25 rows)
1022 -- multiple CTEs
1023 with recursive
1024 graph(f, t, label) as (
1025   values (1, 2, 'arc 1 -> 2'),
1026          (1, 3, 'arc 1 -> 3'),
1027          (2, 3, 'arc 2 -> 3'),
1028          (1, 4, 'arc 1 -> 4'),
1029          (4, 5, 'arc 4 -> 5'),
1030          (5, 1, 'arc 5 -> 1')
1032 search_graph(f, t, label) as (
1033         select * from graph g
1034         union all
1035         select g.*
1036         from graph g, search_graph sg
1037         where g.f = sg.t
1038 ) cycle f, t set is_cycle to true default false using path
1039 select f, t, label from search_graph;
1040  f | t |   label    
1041 ---+---+------------
1042  1 | 2 | arc 1 -> 2
1043  1 | 3 | arc 1 -> 3
1044  2 | 3 | arc 2 -> 3
1045  1 | 4 | arc 1 -> 4
1046  4 | 5 | arc 4 -> 5
1047  5 | 1 | arc 5 -> 1
1048  2 | 3 | arc 2 -> 3
1049  4 | 5 | arc 4 -> 5
1050  5 | 1 | arc 5 -> 1
1051  1 | 4 | arc 1 -> 4
1052  1 | 3 | arc 1 -> 3
1053  1 | 2 | arc 1 -> 2
1054  5 | 1 | arc 5 -> 1
1055  1 | 4 | arc 1 -> 4
1056  1 | 3 | arc 1 -> 3
1057  1 | 2 | arc 1 -> 2
1058  4 | 5 | arc 4 -> 5
1059  2 | 3 | arc 2 -> 3
1060  1 | 4 | arc 1 -> 4
1061  1 | 3 | arc 1 -> 3
1062  1 | 2 | arc 1 -> 2
1063  4 | 5 | arc 4 -> 5
1064  2 | 3 | arc 2 -> 3
1065  5 | 1 | arc 5 -> 1
1066  2 | 3 | arc 2 -> 3
1067 (25 rows)
1069 -- star expansion
1070 with recursive a as (
1071         select 1 as b
1072         union all
1073         select * from a
1074 ) cycle b set c using p
1075 select * from a;
1076  b | c |     p     
1077 ---+---+-----------
1078  1 | f | {(1)}
1079  1 | t | {(1),(1)}
1080 (2 rows)
1082 -- search+cycle
1083 with recursive search_graph(f, t, label) as (
1084         select * from graph g
1085         union all
1086         select g.*
1087         from graph g, search_graph sg
1088         where g.f = sg.t
1089 ) search depth first by f, t set seq
1090   cycle f, t set is_cycle using path
1091 select * from search_graph;
1092  f | t |   label    |                    seq                    | is_cycle |                   path                    
1093 ---+---+------------+-------------------------------------------+----------+-------------------------------------------
1094  1 | 2 | arc 1 -> 2 | {"(1,2)"}                                 | f        | {"(1,2)"}
1095  1 | 3 | arc 1 -> 3 | {"(1,3)"}                                 | f        | {"(1,3)"}
1096  2 | 3 | arc 2 -> 3 | {"(2,3)"}                                 | f        | {"(2,3)"}
1097  1 | 4 | arc 1 -> 4 | {"(1,4)"}                                 | f        | {"(1,4)"}
1098  4 | 5 | arc 4 -> 5 | {"(4,5)"}                                 | f        | {"(4,5)"}
1099  5 | 1 | arc 5 -> 1 | {"(5,1)"}                                 | f        | {"(5,1)"}
1100  1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"}                         | f        | {"(5,1)","(1,2)"}
1101  1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"}                         | f        | {"(5,1)","(1,3)"}
1102  1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"}                         | f        | {"(5,1)","(1,4)"}
1103  2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}                         | f        | {"(1,2)","(2,3)"}
1104  4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}                         | f        | {"(1,4)","(4,5)"}
1105  5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"}                         | f        | {"(4,5)","(5,1)"}
1106  1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"}                 | f        | {"(4,5)","(5,1)","(1,2)"}
1107  1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"}                 | f        | {"(4,5)","(5,1)","(1,3)"}
1108  1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"}                 | f        | {"(4,5)","(5,1)","(1,4)"}
1109  2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"}                 | f        | {"(5,1)","(1,2)","(2,3)"}
1110  4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"}                 | f        | {"(5,1)","(1,4)","(4,5)"}
1111  5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"}                 | f        | {"(1,4)","(4,5)","(5,1)"}
1112  1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"}         | f        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
1113  1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"}         | f        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
1114  1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"}         | t        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
1115  2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"}         | f        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
1116  4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"}         | t        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
1117  5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"}         | t        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
1118  2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
1119 (25 rows)
1121 with recursive search_graph(f, t, label) as (
1122         select * from graph g
1123         union all
1124         select g.*
1125         from graph g, search_graph sg
1126         where g.f = sg.t
1127 ) search breadth first by f, t set seq
1128   cycle f, t set is_cycle using path
1129 select * from search_graph;
1130  f | t |   label    |   seq   | is_cycle |                   path                    
1131 ---+---+------------+---------+----------+-------------------------------------------
1132  1 | 2 | arc 1 -> 2 | (0,1,2) | f        | {"(1,2)"}
1133  1 | 3 | arc 1 -> 3 | (0,1,3) | f        | {"(1,3)"}
1134  2 | 3 | arc 2 -> 3 | (0,2,3) | f        | {"(2,3)"}
1135  1 | 4 | arc 1 -> 4 | (0,1,4) | f        | {"(1,4)"}
1136  4 | 5 | arc 4 -> 5 | (0,4,5) | f        | {"(4,5)"}
1137  5 | 1 | arc 5 -> 1 | (0,5,1) | f        | {"(5,1)"}
1138  1 | 2 | arc 1 -> 2 | (1,1,2) | f        | {"(5,1)","(1,2)"}
1139  1 | 3 | arc 1 -> 3 | (1,1,3) | f        | {"(5,1)","(1,3)"}
1140  1 | 4 | arc 1 -> 4 | (1,1,4) | f        | {"(5,1)","(1,4)"}
1141  2 | 3 | arc 2 -> 3 | (1,2,3) | f        | {"(1,2)","(2,3)"}
1142  4 | 5 | arc 4 -> 5 | (1,4,5) | f        | {"(1,4)","(4,5)"}
1143  5 | 1 | arc 5 -> 1 | (1,5,1) | f        | {"(4,5)","(5,1)"}
1144  1 | 2 | arc 1 -> 2 | (2,1,2) | f        | {"(4,5)","(5,1)","(1,2)"}
1145  1 | 3 | arc 1 -> 3 | (2,1,3) | f        | {"(4,5)","(5,1)","(1,3)"}
1146  1 | 4 | arc 1 -> 4 | (2,1,4) | f        | {"(4,5)","(5,1)","(1,4)"}
1147  2 | 3 | arc 2 -> 3 | (2,2,3) | f        | {"(5,1)","(1,2)","(2,3)"}
1148  4 | 5 | arc 4 -> 5 | (2,4,5) | f        | {"(5,1)","(1,4)","(4,5)"}
1149  5 | 1 | arc 5 -> 1 | (2,5,1) | f        | {"(1,4)","(4,5)","(5,1)"}
1150  1 | 2 | arc 1 -> 2 | (3,1,2) | f        | {"(1,4)","(4,5)","(5,1)","(1,2)"}
1151  1 | 3 | arc 1 -> 3 | (3,1,3) | f        | {"(1,4)","(4,5)","(5,1)","(1,3)"}
1152  1 | 4 | arc 1 -> 4 | (3,1,4) | t        | {"(1,4)","(4,5)","(5,1)","(1,4)"}
1153  2 | 3 | arc 2 -> 3 | (3,2,3) | f        | {"(4,5)","(5,1)","(1,2)","(2,3)"}
1154  4 | 5 | arc 4 -> 5 | (3,4,5) | t        | {"(4,5)","(5,1)","(1,4)","(4,5)"}
1155  5 | 1 | arc 5 -> 1 | (3,5,1) | t        | {"(5,1)","(1,4)","(4,5)","(5,1)"}
1156  2 | 3 | arc 2 -> 3 | (4,2,3) | f        | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
1157 (25 rows)
1159 -- various syntax errors
1160 with recursive search_graph(f, t, label) as (
1161         select * from graph g
1162         union all
1163         select g.*
1164         from graph g, search_graph sg
1165         where g.f = sg.t
1166 ) cycle foo, tar set is_cycle using path
1167 select * from search_graph;
1168 ERROR:  cycle column "foo" not in WITH query column list
1169 LINE 7: ) cycle foo, tar set is_cycle using path
1170           ^
1171 with recursive search_graph(f, t, label) as (
1172         select * from graph g
1173         union all
1174         select g.*
1175         from graph g, search_graph sg
1176         where g.f = sg.t
1177 ) cycle f, t set is_cycle to true default 55 using path
1178 select * from search_graph;
1179 ERROR:  CYCLE types boolean and integer cannot be matched
1180 LINE 7: ) cycle f, t set is_cycle to true default 55 using path
1181                                                   ^
1182 with recursive search_graph(f, t, label) as (
1183         select * from graph g
1184         union all
1185         select g.*
1186         from graph g, search_graph sg
1187         where g.f = sg.t
1188 ) cycle f, t set is_cycle to point '(1,1)' default point '(0,0)' using path
1189 select * from search_graph;
1190 ERROR:  could not identify an equality operator for type point
1191 with recursive search_graph(f, t, label) as (
1192         select * from graph g
1193         union all
1194         select g.*
1195         from graph g, search_graph sg
1196         where g.f = sg.t
1197 ) cycle f, t set label to true default false using path
1198 select * from search_graph;
1199 ERROR:  cycle mark column name "label" already used in WITH query column list
1200 LINE 7: ) cycle f, t set label to true default false using path
1201           ^
1202 with recursive search_graph(f, t, label) as (
1203         select * from graph g
1204         union all
1205         select g.*
1206         from graph g, search_graph sg
1207         where g.f = sg.t
1208 ) cycle f, t set is_cycle to true default false using label
1209 select * from search_graph;
1210 ERROR:  cycle path column name "label" already used in WITH query column list
1211 LINE 7: ) cycle f, t set is_cycle to true default false using label
1212           ^
1213 with recursive search_graph(f, t, label) as (
1214         select * from graph g
1215         union all
1216         select g.*
1217         from graph g, search_graph sg
1218         where g.f = sg.t
1219 ) cycle f, t set foo to true default false using foo
1220 select * from search_graph;
1221 ERROR:  cycle mark column name and cycle path column name are the same
1222 LINE 7: ) cycle f, t set foo to true default false using foo
1223           ^
1224 with recursive search_graph(f, t, label) as (
1225         select * from graph g
1226         union all
1227         select g.*
1228         from graph g, search_graph sg
1229         where g.f = sg.t
1230 ) cycle f, t, f set is_cycle to true default false using path
1231 select * from search_graph;
1232 ERROR:  cycle column "f" specified more than once
1233 LINE 7: ) cycle f, t, f set is_cycle to true default false using pat...
1234           ^
1235 with recursive search_graph(f, t, label) as (
1236         select * from graph g
1237         union all
1238         select g.*
1239         from graph g, search_graph sg
1240         where g.f = sg.t
1241 ) search depth first by f, t set foo
1242   cycle f, t set foo to true default false using path
1243 select * from search_graph;
1244 ERROR:  search sequence column name and cycle mark column name are the same
1245 LINE 7: ) search depth first by f, t set foo
1246           ^
1247 with recursive search_graph(f, t, label) as (
1248         select * from graph g
1249         union all
1250         select g.*
1251         from graph g, search_graph sg
1252         where g.f = sg.t
1253 ) search depth first by f, t set foo
1254   cycle f, t set is_cycle to true default false using foo
1255 select * from search_graph;
1256 ERROR:  search sequence column name and cycle path column name are the same
1257 LINE 7: ) search depth first by f, t set foo
1258           ^
1259 -- test ruleutils and view expansion
1260 create temp view v_cycle1 as
1261 with recursive search_graph(f, t, label) as (
1262         select * from graph g
1263         union all
1264         select g.*
1265         from graph g, search_graph sg
1266         where g.f = sg.t
1267 ) cycle f, t set is_cycle using path
1268 select f, t, label from search_graph;
1269 create temp view v_cycle2 as
1270 with recursive search_graph(f, t, label) as (
1271         select * from graph g
1272         union all
1273         select g.*
1274         from graph g, search_graph sg
1275         where g.f = sg.t
1276 ) cycle f, t set is_cycle to 'Y' default 'N' using path
1277 select f, t, label from search_graph;
1278 select pg_get_viewdef('v_cycle1');
1279                  pg_get_viewdef                 
1280 ------------------------------------------------
1281   WITH RECURSIVE search_graph(f, t, label) AS (+
1282           SELECT g.f,                          +
1283              g.t,                              +
1284              g.label                           +
1285             FROM graph g                       +
1286          UNION ALL                             +
1287           SELECT g.f,                          +
1288              g.t,                              +
1289              g.label                           +
1290             FROM graph g,                      +
1291              search_graph sg                   +
1292            WHERE (g.f = sg.t)                  +
1293          ) CYCLE f, t SET is_cycle USING path  +
1294   SELECT search_graph.f,                       +
1295      search_graph.t,                           +
1296      search_graph.label                        +
1297     FROM search_graph;
1298 (1 row)
1300 select pg_get_viewdef('v_cycle2');
1301                                pg_get_viewdef                                
1302 -----------------------------------------------------------------------------
1303   WITH RECURSIVE search_graph(f, t, label) AS (                             +
1304           SELECT g.f,                                                       +
1305              g.t,                                                           +
1306              g.label                                                        +
1307             FROM graph g                                                    +
1308          UNION ALL                                                          +
1309           SELECT g.f,                                                       +
1310              g.t,                                                           +
1311              g.label                                                        +
1312             FROM graph g,                                                   +
1313              search_graph sg                                                +
1314            WHERE (g.f = sg.t)                                               +
1315          ) CYCLE f, t SET is_cycle TO 'Y'::text DEFAULT 'N'::text USING path+
1316   SELECT search_graph.f,                                                    +
1317      search_graph.t,                                                        +
1318      search_graph.label                                                     +
1319     FROM search_graph;
1320 (1 row)
1322 select * from v_cycle1;
1323  f | t |   label    
1324 ---+---+------------
1325  1 | 2 | arc 1 -> 2
1326  1 | 3 | arc 1 -> 3
1327  2 | 3 | arc 2 -> 3
1328  1 | 4 | arc 1 -> 4
1329  4 | 5 | arc 4 -> 5
1330  5 | 1 | arc 5 -> 1
1331  1 | 2 | arc 1 -> 2
1332  1 | 3 | arc 1 -> 3
1333  1 | 4 | arc 1 -> 4
1334  2 | 3 | arc 2 -> 3
1335  4 | 5 | arc 4 -> 5
1336  5 | 1 | arc 5 -> 1
1337  1 | 2 | arc 1 -> 2
1338  1 | 3 | arc 1 -> 3
1339  1 | 4 | arc 1 -> 4
1340  2 | 3 | arc 2 -> 3
1341  4 | 5 | arc 4 -> 5
1342  5 | 1 | arc 5 -> 1
1343  1 | 2 | arc 1 -> 2
1344  1 | 3 | arc 1 -> 3
1345  1 | 4 | arc 1 -> 4
1346  2 | 3 | arc 2 -> 3
1347  4 | 5 | arc 4 -> 5
1348  5 | 1 | arc 5 -> 1
1349  2 | 3 | arc 2 -> 3
1350 (25 rows)
1352 select * from v_cycle2;
1353  f | t |   label    
1354 ---+---+------------
1355  1 | 2 | arc 1 -> 2
1356  1 | 3 | arc 1 -> 3
1357  2 | 3 | arc 2 -> 3
1358  1 | 4 | arc 1 -> 4
1359  4 | 5 | arc 4 -> 5
1360  5 | 1 | arc 5 -> 1
1361  1 | 2 | arc 1 -> 2
1362  1 | 3 | arc 1 -> 3
1363  1 | 4 | arc 1 -> 4
1364  2 | 3 | arc 2 -> 3
1365  4 | 5 | arc 4 -> 5
1366  5 | 1 | arc 5 -> 1
1367  1 | 2 | arc 1 -> 2
1368  1 | 3 | arc 1 -> 3
1369  1 | 4 | arc 1 -> 4
1370  2 | 3 | arc 2 -> 3
1371  4 | 5 | arc 4 -> 5
1372  5 | 1 | arc 5 -> 1
1373  1 | 2 | arc 1 -> 2
1374  1 | 3 | arc 1 -> 3
1375  1 | 4 | arc 1 -> 4
1376  2 | 3 | arc 2 -> 3
1377  4 | 5 | arc 4 -> 5
1378  5 | 1 | arc 5 -> 1
1379  2 | 3 | arc 2 -> 3
1380 (25 rows)
1383 -- test multiple WITH queries
1385 WITH RECURSIVE
1386   y (id) AS (VALUES (1)),
1387   x (id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5)
1388 SELECT * FROM x;
1389  id 
1390 ----
1391   1
1392   2
1393   3
1394   4
1395   5
1396 (5 rows)
1398 -- forward reference OK
1399 WITH RECURSIVE
1400     x(id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5),
1401     y(id) AS (values (1))
1402  SELECT * FROM x;
1403  id 
1404 ----
1405   1
1406   2
1407   3
1408   4
1409   5
1410 (5 rows)
1412 WITH RECURSIVE
1413    x(id) AS
1414      (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5),
1415    y(id) AS
1416      (VALUES (1) UNION ALL SELECT id+1 FROM y WHERE id < 10)
1417  SELECT y.*, x.* FROM y LEFT JOIN x USING (id);
1418  id | id 
1419 ----+----
1420   1 |  1
1421   2 |  2
1422   3 |  3
1423   4 |  4
1424   5 |  5
1425   6 |   
1426   7 |   
1427   8 |   
1428   9 |   
1429  10 |   
1430 (10 rows)
1432 WITH RECURSIVE
1433    x(id) AS
1434      (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5),
1435    y(id) AS
1436      (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 10)
1437  SELECT y.*, x.* FROM y LEFT JOIN x USING (id);
1438  id | id 
1439 ----+----
1440   1 |  1
1441   2 |  2
1442   3 |  3
1443   4 |  4
1444   5 |  5
1445   6 |   
1446 (6 rows)
1448 WITH RECURSIVE
1449    x(id) AS
1450      (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ),
1451    y(id) AS
1452      (SELECT * FROM x UNION ALL SELECT * FROM x),
1453    z(id) AS
1454      (SELECT * FROM x UNION ALL SELECT id+1 FROM z WHERE id < 10)
1455  SELECT * FROM z;
1456  id 
1457 ----
1458   1
1459   2
1460   3
1461   2
1462   3
1463   4
1464   3
1465   4
1466   5
1467   4
1468   5
1469   6
1470   5
1471   6
1472   7
1473   6
1474   7
1475   8
1476   7
1477   8
1478   9
1479   8
1480   9
1481  10
1482   9
1483  10
1484  10
1485 (27 rows)
1487 WITH RECURSIVE
1488    x(id) AS
1489      (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ),
1490    y(id) AS
1491      (SELECT * FROM x UNION ALL SELECT * FROM x),
1492    z(id) AS
1493      (SELECT * FROM y UNION ALL SELECT id+1 FROM z WHERE id < 10)
1494  SELECT * FROM z;
1495  id 
1496 ----
1497   1
1498   2
1499   3
1500   1
1501   2
1502   3
1503   2
1504   3
1505   4
1506   2
1507   3
1508   4
1509   3
1510   4
1511   5
1512   3
1513   4
1514   5
1515   4
1516   5
1517   6
1518   4
1519   5
1520   6
1521   5
1522   6
1523   7
1524   5
1525   6
1526   7
1527   6
1528   7
1529   8
1530   6
1531   7
1532   8
1533   7
1534   8
1535   9
1536   7
1537   8
1538   9
1539   8
1540   9
1541  10
1542   8
1543   9
1544  10
1545   9
1546  10
1547   9
1548  10
1549  10
1550  10
1551 (54 rows)
1554 -- Test WITH attached to a data-modifying statement
1556 CREATE TEMPORARY TABLE y (a INTEGER);
1557 INSERT INTO y SELECT generate_series(1, 10);
1558 WITH t AS (
1559         SELECT a FROM y
1561 INSERT INTO y
1562 SELECT a+20 FROM t RETURNING *;
1563  a  
1564 ----
1565  21
1566  22
1567  23
1568  24
1569  25
1570  26
1571  27
1572  28
1573  29
1574  30
1575 (10 rows)
1577 SELECT * FROM y;
1578  a  
1579 ----
1580   1
1581   2
1582   3
1583   4
1584   5
1585   6
1586   7
1587   8
1588   9
1589  10
1590  21
1591  22
1592  23
1593  24
1594  25
1595  26
1596  27
1597  28
1598  29
1599  30
1600 (20 rows)
1602 WITH t AS (
1603         SELECT a FROM y
1605 UPDATE y SET a = y.a-10 FROM t WHERE y.a > 20 AND t.a = y.a RETURNING y.a;
1606  a  
1607 ----
1608  11
1609  12
1610  13
1611  14
1612  15
1613  16
1614  17
1615  18
1616  19
1617  20
1618 (10 rows)
1620 SELECT * FROM y;
1621  a  
1622 ----
1623   1
1624   2
1625   3
1626   4
1627   5
1628   6
1629   7
1630   8
1631   9
1632  10
1633  11
1634  12
1635  13
1636  14
1637  15
1638  16
1639  17
1640  18
1641  19
1642  20
1643 (20 rows)
1645 WITH RECURSIVE t(a) AS (
1646         SELECT 11
1647         UNION ALL
1648         SELECT a+1 FROM t WHERE a < 50
1650 DELETE FROM y USING t WHERE t.a = y.a RETURNING y.a;
1651  a  
1652 ----
1653  11
1654  12
1655  13
1656  14
1657  15
1658  16
1659  17
1660  18
1661  19
1662  20
1663 (10 rows)
1665 SELECT * FROM y;
1666  a  
1667 ----
1668   1
1669   2
1670   3
1671   4
1672   5
1673   6
1674   7
1675   8
1676   9
1677  10
1678 (10 rows)
1680 DROP TABLE y;
1682 -- error cases
1684 -- INTERSECT
1685 WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
1686         SELECT * FROM x;
1687 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
1688 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x...
1689                        ^
1690 WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FROM x)
1691         SELECT * FROM x;
1692 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
1693 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FR...
1694                        ^
1695 -- EXCEPT
1696 WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x)
1697         SELECT * FROM x;
1698 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
1699 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x)
1700                        ^
1701 WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM x)
1702         SELECT * FROM x;
1703 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
1704 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM ...
1705                        ^
1706 -- no non-recursive term
1707 WITH RECURSIVE x(n) AS (SELECT n FROM x)
1708         SELECT * FROM x;
1709 ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
1710 LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x)
1711                        ^
1712 -- recursive term in the left hand side (strictly speaking, should allow this)
1713 WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
1714         SELECT * FROM x;
1715 ERROR:  recursive reference to query "x" must not appear within its non-recursive term
1716 LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
1717                                               ^
1718 CREATE TEMPORARY TABLE y (a INTEGER);
1719 INSERT INTO y SELECT generate_series(1, 10);
1720 -- LEFT JOIN
1721 WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
1722         UNION ALL
1723         SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10)
1724 SELECT * FROM x;
1725 ERROR:  recursive reference to query "x" must not appear within an outer join
1726 LINE 3:  SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10)
1727                                        ^
1728 -- RIGHT JOIN
1729 WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
1730         UNION ALL
1731         SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10)
1732 SELECT * FROM x;
1733 ERROR:  recursive reference to query "x" must not appear within an outer join
1734 LINE 3:  SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10)
1735                            ^
1736 -- FULL JOIN
1737 WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
1738         UNION ALL
1739         SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10)
1740 SELECT * FROM x;
1741 ERROR:  recursive reference to query "x" must not appear within an outer join
1742 LINE 3:  SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10)
1743                            ^
1744 -- subquery
1745 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x
1746                           WHERE n IN (SELECT * FROM x))
1747   SELECT * FROM x;
1748 ERROR:  recursive reference to query "x" must not appear within a subquery
1749 LINE 2:                           WHERE n IN (SELECT * FROM x))
1750                                                             ^
1751 -- aggregate functions
1752 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) FROM x)
1753   SELECT * FROM x;
1754 ERROR:  aggregate functions are not allowed in a recursive query's recursive term
1755 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) F...
1756                                                           ^
1757 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FROM x)
1758   SELECT * FROM x;
1759 ERROR:  aggregate functions are not allowed in a recursive query's recursive term
1760 LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FRO...
1761                                                           ^
1762 -- ORDER BY
1763 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1)
1764   SELECT * FROM x;
1765 ERROR:  ORDER BY in a recursive query is not implemented
1766 LINE 1: ...VE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1)
1767                                                                      ^
1768 -- LIMIT/OFFSET
1769 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1)
1770   SELECT * FROM x;
1771 ERROR:  OFFSET in a recursive query is not implemented
1772 LINE 1: ... AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1)
1773                                                                      ^
1774 -- FOR UPDATE
1775 WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x FOR UPDATE)
1776   SELECT * FROM x;
1777 ERROR:  FOR UPDATE/SHARE in a recursive query is not implemented
1778 -- target list has a recursive query name
1779 WITH RECURSIVE x(id) AS (values (1)
1780     UNION ALL
1781     SELECT (SELECT * FROM x) FROM x WHERE id < 5
1782 ) SELECT * FROM x;
1783 ERROR:  recursive reference to query "x" must not appear within a subquery
1784 LINE 3:     SELECT (SELECT * FROM x) FROM x WHERE id < 5
1785                                   ^
1786 -- mutual recursive query (not implemented)
1787 WITH RECURSIVE
1788   x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id < 5),
1789   y (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 5)
1790 SELECT * FROM x;
1791 ERROR:  mutual recursion between WITH items is not implemented
1792 LINE 2:   x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id ...
1793           ^
1794 -- non-linear recursion is not allowed
1795 WITH RECURSIVE foo(i) AS
1796     (values (1)
1797     UNION ALL
1798        (SELECT i+1 FROM foo WHERE i < 10
1799           UNION ALL
1800        SELECT i+1 FROM foo WHERE i < 5)
1801 ) SELECT * FROM foo;
1802 ERROR:  recursive reference to query "foo" must not appear more than once
1803 LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
1804                                ^
1805 WITH RECURSIVE foo(i) AS
1806     (values (1)
1807     UNION ALL
1808            SELECT * FROM
1809        (SELECT i+1 FROM foo WHERE i < 10
1810           UNION ALL
1811        SELECT i+1 FROM foo WHERE i < 5) AS t
1812 ) SELECT * FROM foo;
1813 ERROR:  recursive reference to query "foo" must not appear more than once
1814 LINE 7:        SELECT i+1 FROM foo WHERE i < 5) AS t
1815                                ^
1816 WITH RECURSIVE foo(i) AS
1817     (values (1)
1818     UNION ALL
1819        (SELECT i+1 FROM foo WHERE i < 10
1820           EXCEPT
1821        SELECT i+1 FROM foo WHERE i < 5)
1822 ) SELECT * FROM foo;
1823 ERROR:  recursive reference to query "foo" must not appear within EXCEPT
1824 LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
1825                                ^
1826 WITH RECURSIVE foo(i) AS
1827     (values (1)
1828     UNION ALL
1829        (SELECT i+1 FROM foo WHERE i < 10
1830           INTERSECT
1831        SELECT i+1 FROM foo WHERE i < 5)
1832 ) SELECT * FROM foo;
1833 ERROR:  recursive reference to query "foo" must not appear more than once
1834 LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
1835                                ^
1836 -- Wrong type induced from non-recursive term
1837 WITH RECURSIVE foo(i) AS
1838    (SELECT i FROM (VALUES(1),(2)) t(i)
1839    UNION ALL
1840    SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
1841 SELECT * FROM foo;
1842 ERROR:  recursive query "foo" column 1 has type integer in non-recursive term but type numeric overall
1843 LINE 2:    (SELECT i FROM (VALUES(1),(2)) t(i)
1844                    ^
1845 HINT:  Cast the output of the non-recursive term to the correct type.
1846 -- rejects different typmod, too (should we allow this?)
1847 WITH RECURSIVE foo(i) AS
1848    (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
1849    UNION ALL
1850    SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
1851 SELECT * FROM foo;
1852 ERROR:  recursive query "foo" column 1 has type numeric(3,0) in non-recursive term but type numeric overall
1853 LINE 2:    (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
1854                    ^
1855 HINT:  Cast the output of the non-recursive term to the correct type.
1856 -- disallow OLD/NEW reference in CTE
1857 CREATE TEMPORARY TABLE x (n integer);
1858 CREATE RULE r2 AS ON UPDATE TO x DO INSTEAD
1859     WITH t AS (SELECT OLD.*) UPDATE y SET a = t.n FROM t;
1860 ERROR:  cannot refer to OLD within WITH query
1862 -- test for bug #4902
1864 with cte(foo) as ( values(42) ) values((select foo from cte));
1865  column1 
1866 ---------
1867       42
1868 (1 row)
1870 with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q;
1871  foo 
1872 -----
1873   42
1874 (1 row)
1876 -- test CTE referencing an outer-level variable (to see that changed-parameter
1877 -- signaling still works properly after fixing this bug)
1878 select ( with cte(foo) as ( values(f1) )
1879          select (select foo from cte) )
1880 from int4_tbl;
1881      foo     
1882 -------------
1883            0
1884       123456
1885      -123456
1886   2147483647
1887  -2147483647
1888 (5 rows)
1890 select ( with cte(foo) as ( values(f1) )
1891           values((select foo from cte)) )
1892 from int4_tbl;
1893    column1   
1894 -------------
1895            0
1896       123456
1897      -123456
1898   2147483647
1899  -2147483647
1900 (5 rows)
1903 -- test for nested-recursive-WITH bug
1905 WITH RECURSIVE t(j) AS (
1906     WITH RECURSIVE s(i) AS (
1907         VALUES (1)
1908         UNION ALL
1909         SELECT i+1 FROM s WHERE i < 10
1910     )
1911     SELECT i FROM s
1912     UNION ALL
1913     SELECT j+1 FROM t WHERE j < 10
1915 SELECT * FROM t;
1916  j  
1917 ----
1918   1
1919   2
1920   3
1921   4
1922   5
1923   6
1924   7
1925   8
1926   9
1927  10
1928   2
1929   3
1930   4
1931   5
1932   6
1933   7
1934   8
1935   9
1936  10
1937   3
1938   4
1939   5
1940   6
1941   7
1942   8
1943   9
1944  10
1945   4
1946   5
1947   6
1948   7
1949   8
1950   9
1951  10
1952   5
1953   6
1954   7
1955   8
1956   9
1957  10
1958   6
1959   7
1960   8
1961   9
1962  10
1963   7
1964   8
1965   9
1966  10
1967   8
1968   9
1969  10
1970   9
1971  10
1972  10
1973 (55 rows)
1976 -- test WITH attached to intermediate-level set operation
1978 WITH outermost(x) AS (
1979   SELECT 1
1980   UNION (WITH innermost as (SELECT 2)
1981          SELECT * FROM innermost
1982          UNION SELECT 3)
1984 SELECT * FROM outermost ORDER BY 1;
1985  x 
1990 (3 rows)
1992 WITH outermost(x) AS (
1993   SELECT 1
1994   UNION (WITH innermost as (SELECT 2)
1995          SELECT * FROM outermost  -- fail
1996          UNION SELECT * FROM innermost)
1998 SELECT * FROM outermost ORDER BY 1;
1999 ERROR:  relation "outermost" does not exist
2000 LINE 4:          SELECT * FROM outermost  
2001                                ^
2002 DETAIL:  There is a WITH item named "outermost", but it cannot be referenced from this part of the query.
2003 HINT:  Use WITH RECURSIVE, or re-order the WITH items to remove forward references.
2004 WITH RECURSIVE outermost(x) AS (
2005   SELECT 1
2006   UNION (WITH innermost as (SELECT 2)
2007          SELECT * FROM outermost
2008          UNION SELECT * FROM innermost)
2010 SELECT * FROM outermost ORDER BY 1;
2011  x 
2015 (2 rows)
2017 WITH RECURSIVE outermost(x) AS (
2018   WITH innermost as (SELECT 2 FROM outermost) -- fail
2019     SELECT * FROM innermost
2020     UNION SELECT * from outermost
2022 SELECT * FROM outermost ORDER BY 1;
2023 ERROR:  recursive reference to query "outermost" must not appear within a subquery
2024 LINE 2:   WITH innermost as (SELECT 2 FROM outermost) 
2025                                            ^
2027 -- This test will fail with the old implementation of PARAM_EXEC parameter
2028 -- assignment, because the "q1" Var passed down to A's targetlist subselect
2029 -- looks exactly like the "A.id" Var passed down to C's subselect, causing
2030 -- the old code to give them the same runtime PARAM_EXEC slot.  But the
2031 -- lifespans of the two parameters overlap, thanks to B also reading A.
2033 with
2034 A as ( select q2 as id, (select q1) as x from int8_tbl ),
2035 B as ( select id, row_number() over (partition by id) as r from A ),
2036 C as ( select A.id, array(select B.id from B where B.id = A.id) from A )
2037 select * from C;
2038         id         |                array                
2039 -------------------+-------------------------------------
2040                456 | {456}
2041   4567890123456789 | {4567890123456789,4567890123456789}
2042                123 | {123}
2043   4567890123456789 | {4567890123456789,4567890123456789}
2044  -4567890123456789 | {-4567890123456789}
2045 (5 rows)
2048 -- Test CTEs read in non-initialization orders
2050 WITH RECURSIVE
2051   tab(id_key,link) AS (VALUES (1,17), (2,17), (3,17), (4,17), (6,17), (5,17)),
2052   iter (id_key, row_type, link) AS (
2053       SELECT 0, 'base', 17
2054     UNION ALL (
2055       WITH remaining(id_key, row_type, link, min) AS (
2056         SELECT tab.id_key, 'true'::text, iter.link, MIN(tab.id_key) OVER ()
2057         FROM tab INNER JOIN iter USING (link)
2058         WHERE tab.id_key > iter.id_key
2059       ),
2060       first_remaining AS (
2061         SELECT id_key, row_type, link
2062         FROM remaining
2063         WHERE id_key=min
2064       ),
2065       effect AS (
2066         SELECT tab.id_key, 'new'::text, tab.link
2067         FROM first_remaining e INNER JOIN tab ON e.id_key=tab.id_key
2068         WHERE e.row_type = 'false'
2069       )
2070       SELECT * FROM first_remaining
2071       UNION ALL SELECT * FROM effect
2072     )
2073   )
2074 SELECT * FROM iter;
2075  id_key | row_type | link 
2076 --------+----------+------
2077       0 | base     |   17
2078       1 | true     |   17
2079       2 | true     |   17
2080       3 | true     |   17
2081       4 | true     |   17
2082       5 | true     |   17
2083       6 | true     |   17
2084 (7 rows)
2086 WITH RECURSIVE
2087   tab(id_key,link) AS (VALUES (1,17), (2,17), (3,17), (4,17), (6,17), (5,17)),
2088   iter (id_key, row_type, link) AS (
2089       SELECT 0, 'base', 17
2090     UNION (
2091       WITH remaining(id_key, row_type, link, min) AS (
2092         SELECT tab.id_key, 'true'::text, iter.link, MIN(tab.id_key) OVER ()
2093         FROM tab INNER JOIN iter USING (link)
2094         WHERE tab.id_key > iter.id_key
2095       ),
2096       first_remaining AS (
2097         SELECT id_key, row_type, link
2098         FROM remaining
2099         WHERE id_key=min
2100       ),
2101       effect AS (
2102         SELECT tab.id_key, 'new'::text, tab.link
2103         FROM first_remaining e INNER JOIN tab ON e.id_key=tab.id_key
2104         WHERE e.row_type = 'false'
2105       )
2106       SELECT * FROM first_remaining
2107       UNION ALL SELECT * FROM effect
2108     )
2109   )
2110 SELECT * FROM iter;
2111  id_key | row_type | link 
2112 --------+----------+------
2113       0 | base     |   17
2114       1 | true     |   17
2115       2 | true     |   17
2116       3 | true     |   17
2117       4 | true     |   17
2118       5 | true     |   17
2119       6 | true     |   17
2120 (7 rows)
2123 -- Data-modifying statements in WITH
2125 -- INSERT ... RETURNING
2126 WITH t AS (
2127     INSERT INTO y
2128     VALUES
2129         (11),
2130         (12),
2131         (13),
2132         (14),
2133         (15),
2134         (16),
2135         (17),
2136         (18),
2137         (19),
2138         (20)
2139     RETURNING *
2141 SELECT * FROM t;
2142  a  
2143 ----
2144  11
2145  12
2146  13
2147  14
2148  15
2149  16
2150  17
2151  18
2152  19
2153  20
2154 (10 rows)
2156 SELECT * FROM y;
2157  a  
2158 ----
2159   1
2160   2
2161   3
2162   4
2163   5
2164   6
2165   7
2166   8
2167   9
2168  10
2169  11
2170  12
2171  13
2172  14
2173  15
2174  16
2175  17
2176  18
2177  19
2178  20
2179 (20 rows)
2181 -- UPDATE ... RETURNING
2182 WITH t AS (
2183     UPDATE y
2184     SET a=a+1
2185     RETURNING *
2187 SELECT * FROM t;
2188  a  
2189 ----
2190   2
2191   3
2192   4
2193   5
2194   6
2195   7
2196   8
2197   9
2198  10
2199  11
2200  12
2201  13
2202  14
2203  15
2204  16
2205  17
2206  18
2207  19
2208  20
2209  21
2210 (20 rows)
2212 SELECT * FROM y;
2213  a  
2214 ----
2215   2
2216   3
2217   4
2218   5
2219   6
2220   7
2221   8
2222   9
2223  10
2224  11
2225  12
2226  13
2227  14
2228  15
2229  16
2230  17
2231  18
2232  19
2233  20
2234  21
2235 (20 rows)
2237 -- DELETE ... RETURNING
2238 WITH t AS (
2239     DELETE FROM y
2240     WHERE a <= 10
2241     RETURNING *
2243 SELECT * FROM t;
2244  a  
2245 ----
2246   2
2247   3
2248   4
2249   5
2250   6
2251   7
2252   8
2253   9
2254  10
2255 (9 rows)
2257 SELECT * FROM y;
2258  a  
2259 ----
2260  11
2261  12
2262  13
2263  14
2264  15
2265  16
2266  17
2267  18
2268  19
2269  20
2270  21
2271 (11 rows)
2273 -- forward reference
2274 WITH RECURSIVE t AS (
2275         INSERT INTO y
2276                 SELECT a+5 FROM t2 WHERE a > 5
2277         RETURNING *
2278 ), t2 AS (
2279         UPDATE y SET a=a-11 RETURNING *
2281 SELECT * FROM t
2282 UNION ALL
2283 SELECT * FROM t2;
2284  a  
2285 ----
2286  11
2287  12
2288  13
2289  14
2290  15
2291   0
2292   1
2293   2
2294   3
2295   4
2296   5
2297   6
2298   7
2299   8
2300   9
2301  10
2302 (16 rows)
2304 SELECT * FROM y;
2305  a  
2306 ----
2307   0
2308   1
2309   2
2310   3
2311   4
2312   5
2313   6
2314  11
2315   7
2316  12
2317   8
2318  13
2319   9
2320  14
2321  10
2322  15
2323 (16 rows)
2325 -- unconditional DO INSTEAD rule
2326 CREATE RULE y_rule AS ON DELETE TO y DO INSTEAD
2327   INSERT INTO y VALUES(42) RETURNING *;
2328 WITH t AS (
2329         DELETE FROM y RETURNING *
2331 SELECT * FROM t;
2332  a  
2333 ----
2334  42
2335 (1 row)
2337 SELECT * FROM y;
2338  a  
2339 ----
2340   0
2341   1
2342   2
2343   3
2344   4
2345   5
2346   6
2347  11
2348   7
2349  12
2350   8
2351  13
2352   9
2353  14
2354  10
2355  15
2356  42
2357 (17 rows)
2359 DROP RULE y_rule ON y;
2360 -- check merging of outer CTE with CTE in a rule action
2361 CREATE TEMP TABLE bug6051 AS
2362   select i from generate_series(1,3) as t(i);
2363 SELECT * FROM bug6051;
2364  i 
2369 (3 rows)
2371 WITH t1 AS ( DELETE FROM bug6051 RETURNING * )
2372 INSERT INTO bug6051 SELECT * FROM t1;
2373 SELECT * FROM bug6051;
2374  i 
2379 (3 rows)
2381 CREATE TEMP TABLE bug6051_2 (i int);
2382 CREATE RULE bug6051_ins AS ON INSERT TO bug6051 DO INSTEAD
2383  INSERT INTO bug6051_2
2384  SELECT NEW.i;
2385 WITH t1 AS ( DELETE FROM bug6051 RETURNING * )
2386 INSERT INTO bug6051 SELECT * FROM t1;
2387 SELECT * FROM bug6051;
2388  i 
2390 (0 rows)
2392 SELECT * FROM bug6051_2;
2393  i 
2398 (3 rows)
2400 -- a truly recursive CTE in the same list
2401 WITH RECURSIVE t(a) AS (
2402         SELECT 0
2403                 UNION ALL
2404         SELECT a+1 FROM t WHERE a+1 < 5
2405 ), t2 as (
2406         INSERT INTO y
2407                 SELECT * FROM t RETURNING *
2409 SELECT * FROM t2 JOIN y USING (a) ORDER BY a;
2410  a 
2417 (5 rows)
2419 SELECT * FROM y;
2420  a  
2421 ----
2422   0
2423   1
2424   2
2425   3
2426   4
2427   5
2428   6
2429  11
2430   7
2431  12
2432   8
2433  13
2434   9
2435  14
2436  10
2437  15
2438  42
2439   0
2440   1
2441   2
2442   3
2443   4
2444 (22 rows)
2446 -- data-modifying WITH in a modifying statement
2447 WITH t AS (
2448     DELETE FROM y
2449     WHERE a <= 10
2450     RETURNING *
2452 INSERT INTO y SELECT -a FROM t RETURNING *;
2453   a  
2454 -----
2455    0
2456   -1
2457   -2
2458   -3
2459   -4
2460   -5
2461   -6
2462   -7
2463   -8
2464   -9
2465  -10
2466    0
2467   -1
2468   -2
2469   -3
2470   -4
2471 (16 rows)
2473 SELECT * FROM y;
2474   a  
2475 -----
2476   11
2477   12
2478   13
2479   14
2480   15
2481   42
2482    0
2483   -1
2484   -2
2485   -3
2486   -4
2487   -5
2488   -6
2489   -7
2490   -8
2491   -9
2492  -10
2493    0
2494   -1
2495   -2
2496   -3
2497   -4
2498 (22 rows)
2500 -- check that WITH query is run to completion even if outer query isn't
2501 WITH t AS (
2502     UPDATE y SET a = a * 100 RETURNING *
2504 SELECT * FROM t LIMIT 10;
2505   a   
2506 ------
2507  1100
2508  1200
2509  1300
2510  1400
2511  1500
2512  4200
2513     0
2514  -100
2515  -200
2516  -300
2517 (10 rows)
2519 SELECT * FROM y;
2520    a   
2521 -------
2522   1100
2523   1200
2524   1300
2525   1400
2526   1500
2527   4200
2528      0
2529   -100
2530   -200
2531   -300
2532   -400
2533   -500
2534   -600
2535   -700
2536   -800
2537   -900
2538  -1000
2539      0
2540   -100
2541   -200
2542   -300
2543   -400
2544 (22 rows)
2546 -- data-modifying WITH containing INSERT...ON CONFLICT DO UPDATE
2547 CREATE TABLE withz AS SELECT i AS k, (i || ' v')::text v FROM generate_series(1, 16, 3) i;
2548 ALTER TABLE withz ADD UNIQUE (k);
2549 WITH t AS (
2550     INSERT INTO withz SELECT i, 'insert'
2551     FROM generate_series(0, 16) i
2552     ON CONFLICT (k) DO UPDATE SET v = withz.v || ', now update'
2553     RETURNING *
2555 SELECT * FROM t JOIN y ON t.k = y.a ORDER BY a, k;
2556  k |   v    | a 
2557 ---+--------+---
2558  0 | insert | 0
2559  0 | insert | 0
2560 (2 rows)
2562 -- Test EXCLUDED.* reference within CTE
2563 WITH aa AS (
2564     INSERT INTO withz VALUES(1, 5) ON CONFLICT (k) DO UPDATE SET v = EXCLUDED.v
2565     WHERE withz.k != EXCLUDED.k
2566     RETURNING *
2568 SELECT * FROM aa;
2569  k | v 
2570 ---+---
2571 (0 rows)
2573 -- New query/snapshot demonstrates side-effects of previous query.
2574 SELECT * FROM withz ORDER BY k;
2575  k  |        v         
2576 ----+------------------
2577   0 | insert
2578   1 | 1 v, now update
2579   2 | insert
2580   3 | insert
2581   4 | 4 v, now update
2582   5 | insert
2583   6 | insert
2584   7 | 7 v, now update
2585   8 | insert
2586   9 | insert
2587  10 | 10 v, now update
2588  11 | insert
2589  12 | insert
2590  13 | 13 v, now update
2591  14 | insert
2592  15 | insert
2593  16 | 16 v, now update
2594 (17 rows)
2597 -- Ensure subqueries within the update clause work, even if they
2598 -- reference outside values
2600 WITH aa AS (SELECT 1 a, 2 b)
2601 INSERT INTO withz VALUES(1, 'insert')
2602 ON CONFLICT (k) DO UPDATE SET v = (SELECT b || ' update' FROM aa WHERE a = 1 LIMIT 1);
2603 WITH aa AS (SELECT 1 a, 2 b)
2604 INSERT INTO withz VALUES(1, 'insert')
2605 ON CONFLICT (k) DO UPDATE SET v = ' update' WHERE withz.k = (SELECT a FROM aa);
2606 WITH aa AS (SELECT 1 a, 2 b)
2607 INSERT INTO withz VALUES(1, 'insert')
2608 ON CONFLICT (k) DO UPDATE SET v = (SELECT b || ' update' FROM aa WHERE a = 1 LIMIT 1);
2609 WITH aa AS (SELECT 'a' a, 'b' b UNION ALL SELECT 'a' a, 'b' b)
2610 INSERT INTO withz VALUES(1, 'insert')
2611 ON CONFLICT (k) DO UPDATE SET v = (SELECT b || ' update' FROM aa WHERE a = 'a' LIMIT 1);
2612 WITH aa AS (SELECT 1 a, 2 b)
2613 INSERT INTO withz VALUES(1, (SELECT b || ' insert' FROM aa WHERE a = 1 ))
2614 ON CONFLICT (k) DO UPDATE SET v = (SELECT b || ' update' FROM aa WHERE a = 1 LIMIT 1);
2615 -- Update a row more than once, in different parts of a wCTE. That is
2616 -- an allowed, presumably very rare, edge case, but since it was
2617 -- broken in the past, having a test seems worthwhile.
2618 WITH simpletup AS (
2619   SELECT 2 k, 'Green' v),
2620 upsert_cte AS (
2621   INSERT INTO withz VALUES(2, 'Blue') ON CONFLICT (k) DO
2622     UPDATE SET (k, v) = (SELECT k, v FROM simpletup WHERE simpletup.k = withz.k)
2623     RETURNING k, v)
2624 INSERT INTO withz VALUES(2, 'Red') ON CONFLICT (k) DO
2625 UPDATE SET (k, v) = (SELECT k, v FROM upsert_cte WHERE upsert_cte.k = withz.k)
2626 RETURNING k, v;
2627  k | v 
2628 ---+---
2629 (0 rows)
2631 DROP TABLE withz;
2632 -- check that run to completion happens in proper ordering
2633 TRUNCATE TABLE y;
2634 INSERT INTO y SELECT generate_series(1, 3);
2635 CREATE TEMPORARY TABLE yy (a INTEGER);
2636 WITH RECURSIVE t1 AS (
2637   INSERT INTO y SELECT * FROM y RETURNING *
2638 ), t2 AS (
2639   INSERT INTO yy SELECT * FROM t1 RETURNING *
2641 SELECT 1;
2642  ?column? 
2643 ----------
2644         1
2645 (1 row)
2647 SELECT * FROM y;
2648  a 
2656 (6 rows)
2658 SELECT * FROM yy;
2659  a 
2664 (3 rows)
2666 WITH RECURSIVE t1 AS (
2667   INSERT INTO yy SELECT * FROM t2 RETURNING *
2668 ), t2 AS (
2669   INSERT INTO y SELECT * FROM y RETURNING *
2671 SELECT 1;
2672  ?column? 
2673 ----------
2674         1
2675 (1 row)
2677 SELECT * FROM y;
2678  a 
2692 (12 rows)
2694 SELECT * FROM yy;
2695  a 
2706 (9 rows)
2708 -- triggers
2709 TRUNCATE TABLE y;
2710 INSERT INTO y SELECT generate_series(1, 10);
2711 CREATE FUNCTION y_trigger() RETURNS trigger AS $$
2712 begin
2713   raise notice 'y_trigger: a = %', new.a;
2714   return new;
2715 end;
2716 $$ LANGUAGE plpgsql;
2717 CREATE TRIGGER y_trig BEFORE INSERT ON y FOR EACH ROW
2718     EXECUTE PROCEDURE y_trigger();
2719 WITH t AS (
2720     INSERT INTO y
2721     VALUES
2722         (21),
2723         (22),
2724         (23)
2725     RETURNING *
2727 SELECT * FROM t;
2728 NOTICE:  y_trigger: a = 21
2729 NOTICE:  y_trigger: a = 22
2730 NOTICE:  y_trigger: a = 23
2731  a  
2732 ----
2733  21
2734  22
2735  23
2736 (3 rows)
2738 SELECT * FROM y;
2739  a  
2740 ----
2741   1
2742   2
2743   3
2744   4
2745   5
2746   6
2747   7
2748   8
2749   9
2750  10
2751  21
2752  22
2753  23
2754 (13 rows)
2756 DROP TRIGGER y_trig ON y;
2757 CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH ROW
2758     EXECUTE PROCEDURE y_trigger();
2759 WITH t AS (
2760     INSERT INTO y
2761     VALUES
2762         (31),
2763         (32),
2764         (33)
2765     RETURNING *
2767 SELECT * FROM t LIMIT 1;
2768 NOTICE:  y_trigger: a = 31
2769 NOTICE:  y_trigger: a = 32
2770 NOTICE:  y_trigger: a = 33
2771  a  
2772 ----
2773  31
2774 (1 row)
2776 SELECT * FROM y;
2777  a  
2778 ----
2779   1
2780   2
2781   3
2782   4
2783   5
2784   6
2785   7
2786   8
2787   9
2788  10
2789  21
2790  22
2791  23
2792  31
2793  32
2794  33
2795 (16 rows)
2797 DROP TRIGGER y_trig ON y;
2798 CREATE OR REPLACE FUNCTION y_trigger() RETURNS trigger AS $$
2799 begin
2800   raise notice 'y_trigger';
2801   return null;
2802 end;
2803 $$ LANGUAGE plpgsql;
2804 CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH STATEMENT
2805     EXECUTE PROCEDURE y_trigger();
2806 WITH t AS (
2807     INSERT INTO y
2808     VALUES
2809         (41),
2810         (42),
2811         (43)
2812     RETURNING *
2814 SELECT * FROM t;
2815 NOTICE:  y_trigger
2816  a  
2817 ----
2818  41
2819  42
2820  43
2821 (3 rows)
2823 SELECT * FROM y;
2824  a  
2825 ----
2826   1
2827   2
2828   3
2829   4
2830   5
2831   6
2832   7
2833   8
2834   9
2835  10
2836  21
2837  22
2838  23
2839  31
2840  32
2841  33
2842  41
2843  42
2844  43
2845 (19 rows)
2847 DROP TRIGGER y_trig ON y;
2848 DROP FUNCTION y_trigger();
2849 -- WITH attached to inherited UPDATE or DELETE
2850 CREATE TEMP TABLE parent ( id int, val text );
2851 CREATE TEMP TABLE child1 ( ) INHERITS ( parent );
2852 CREATE TEMP TABLE child2 ( ) INHERITS ( parent );
2853 INSERT INTO parent VALUES ( 1, 'p1' );
2854 INSERT INTO child1 VALUES ( 11, 'c11' ),( 12, 'c12' );
2855 INSERT INTO child2 VALUES ( 23, 'c21' ),( 24, 'c22' );
2856 WITH rcte AS ( SELECT sum(id) AS totalid FROM parent )
2857 UPDATE parent SET id = id + totalid FROM rcte;
2858 SELECT * FROM parent;
2859  id | val 
2860 ----+-----
2861  72 | p1
2862  82 | c11
2863  83 | c12
2864  94 | c21
2865  95 | c22
2866 (5 rows)
2868 WITH wcte AS ( INSERT INTO child1 VALUES ( 42, 'new' ) RETURNING id AS newid )
2869 UPDATE parent SET id = id + newid FROM wcte;
2870 SELECT * FROM parent;
2871  id  | val 
2872 -----+-----
2873  114 | p1
2874   42 | new
2875  124 | c11
2876  125 | c12
2877  136 | c21
2878  137 | c22
2879 (6 rows)
2881 WITH rcte AS ( SELECT max(id) AS maxid FROM parent )
2882 DELETE FROM parent USING rcte WHERE id = maxid;
2883 SELECT * FROM parent;
2884  id  | val 
2885 -----+-----
2886  114 | p1
2887   42 | new
2888  124 | c11
2889  125 | c12
2890  136 | c21
2891 (5 rows)
2893 WITH wcte AS ( INSERT INTO child2 VALUES ( 42, 'new2' ) RETURNING id AS newid )
2894 DELETE FROM parent USING wcte WHERE id = newid;
2895 SELECT * FROM parent;
2896  id  | val  
2897 -----+------
2898  114 | p1
2899  124 | c11
2900  125 | c12
2901  136 | c21
2902   42 | new2
2903 (5 rows)
2905 -- check EXPLAIN VERBOSE for a wCTE with RETURNING
2906 EXPLAIN (VERBOSE, COSTS OFF)
2907 WITH wcte AS ( INSERT INTO int8_tbl VALUES ( 42, 47 ) RETURNING q2 )
2908 DELETE FROM a USING wcte WHERE aa = q2;
2909                          QUERY PLAN                         
2910 ------------------------------------------------------------
2911  Delete on public.a
2912    Delete on public.a a_1
2913    Delete on public.b a_2
2914    Delete on public.c a_3
2915    Delete on public.d a_4
2916    CTE wcte
2917      ->  Insert on public.int8_tbl
2918            Output: int8_tbl.q2
2919            ->  Result
2920                  Output: '42'::bigint, '47'::bigint
2921    ->  Hash Join
2922          Output: wcte.*, a.tableoid, a.ctid
2923          Hash Cond: (a.aa = wcte.q2)
2924          ->  Append
2925                ->  Seq Scan on public.a a_1
2926                      Output: a_1.aa, a_1.tableoid, a_1.ctid
2927                ->  Seq Scan on public.b a_2
2928                      Output: a_2.aa, a_2.tableoid, a_2.ctid
2929                ->  Seq Scan on public.c a_3
2930                      Output: a_3.aa, a_3.tableoid, a_3.ctid
2931                ->  Seq Scan on public.d a_4
2932                      Output: a_4.aa, a_4.tableoid, a_4.ctid
2933          ->  Hash
2934                Output: wcte.*, wcte.q2
2935                ->  CTE Scan on wcte
2936                      Output: wcte.*, wcte.q2
2937 (26 rows)
2939 -- error cases
2940 -- data-modifying WITH tries to use its own output
2941 WITH RECURSIVE t AS (
2942         INSERT INTO y
2943                 SELECT * FROM t
2945 VALUES(FALSE);
2946 ERROR:  recursive query "t" must not contain data-modifying statements
2947 LINE 1: WITH RECURSIVE t AS (
2948                        ^
2949 -- no RETURNING in a referenced data-modifying WITH
2950 WITH t AS (
2951         INSERT INTO y VALUES(0)
2953 SELECT * FROM t;
2954 ERROR:  WITH query "t" does not have a RETURNING clause
2955 LINE 4: SELECT * FROM t;
2956                       ^
2957 -- data-modifying WITH allowed only at the top level
2958 SELECT * FROM (
2959         WITH t AS (UPDATE y SET a=a+1 RETURNING *)
2960         SELECT * FROM t
2961 ) ss;
2962 ERROR:  WITH clause containing a data-modifying statement must be at the top level
2963 LINE 2:  WITH t AS (UPDATE y SET a=a+1 RETURNING *)
2964               ^
2965 -- most variants of rules aren't allowed
2966 CREATE RULE y_rule AS ON INSERT TO y WHERE a=0 DO INSTEAD DELETE FROM y;
2967 WITH t AS (
2968         INSERT INTO y VALUES(0)
2970 VALUES(FALSE);
2971 ERROR:  conditional DO INSTEAD rules are not supported for data-modifying statements in WITH
2972 CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTHING;
2973 WITH t AS (
2974         INSERT INTO y VALUES(0)
2976 VALUES(FALSE);
2977 ERROR:  DO INSTEAD NOTHING rules are not supported for data-modifying statements in WITH
2978 CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO INSTEAD NOTIFY foo;
2979 WITH t AS (
2980         INSERT INTO y VALUES(0)
2982 VALUES(FALSE);
2983 ERROR:  DO INSTEAD NOTIFY rules are not supported for data-modifying statements in WITH
2984 CREATE OR REPLACE RULE y_rule AS ON INSERT TO y DO ALSO NOTIFY foo;
2985 WITH t AS (
2986         INSERT INTO y VALUES(0)
2988 VALUES(FALSE);
2989 ERROR:  DO ALSO rules are not supported for data-modifying statements in WITH
2990 CREATE OR REPLACE RULE y_rule AS ON INSERT TO y
2991   DO INSTEAD (NOTIFY foo; NOTIFY bar);
2992 WITH t AS (
2993         INSERT INTO y VALUES(0)
2995 VALUES(FALSE);
2996 ERROR:  multi-statement DO INSTEAD rules are not supported for data-modifying statements in WITH
2997 DROP RULE y_rule ON y;
2998 -- check that parser lookahead for WITH doesn't cause any odd behavior
2999 create table foo (with baz);  -- fail, WITH is a reserved word
3000 ERROR:  syntax error at or near "with"
3001 LINE 1: create table foo (with baz);
3002                           ^
3003 create table foo (with ordinality);  -- fail, WITH is a reserved word
3004 ERROR:  syntax error at or near "with"
3005 LINE 1: create table foo (with ordinality);
3006                           ^
3007 with ordinality as (select 1 as x) select * from ordinality;
3008  x 
3011 (1 row)
3013 -- check sane response to attempt to modify CTE relation
3014 WITH test AS (SELECT 42) INSERT INTO test VALUES (1);
3015 ERROR:  relation "test" does not exist
3016 LINE 1: WITH test AS (SELECT 42) INSERT INTO test VALUES (1);
3017                                              ^
3018 -- check response to attempt to modify table with same name as a CTE (perhaps
3019 -- surprisingly it works, because CTEs don't hide tables from data-modifying
3020 -- statements)
3021 create temp table test (i int);
3022 with test as (select 42) insert into test select * from test;
3023 select * from test;
3024  i  
3025 ----
3026  42
3027 (1 row)
3029 drop table test;