~ubuntu-branches/ubuntu/precise/postgresql-9.1/precise-security

« back to all changes in this revision

Viewing changes to src/test/regress/expected/with.out

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2011-05-11 10:41:53 UTC
  • Revision ID: james.westby@ubuntu.com-20110511104153-psbh2o58553fv1m0
Tags: upstream-9.1~beta1
ImportĀ upstreamĀ versionĀ 9.1~beta1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "department_pkey" for table "department"
 
143
INSERT INTO department VALUES (0, NULL, 'ROOT');
 
144
INSERT INTO department VALUES (1, 0, 'A');
 
145
INSERT INTO department VALUES (2, 1, 'B');
 
146
INSERT INTO department VALUES (3, 2, 'C');
 
147
INSERT INTO department VALUES (4, 2, 'D');
 
148
INSERT INTO department VALUES (5, 0, 'E');
 
149
INSERT INTO department VALUES (6, 4, 'F');
 
150
INSERT INTO department VALUES (7, 5, 'G');
 
151
-- extract all departments under 'A'. Result should be A, B, C, D and F
 
152
WITH RECURSIVE subdepartment AS
 
153
(
 
154
        -- non recursive term
 
155
        SELECT name as root_name, * FROM department WHERE name = 'A'
 
156
        UNION ALL
 
157
        -- recursive term
 
158
        SELECT sd.root_name, d.* FROM department AS d, subdepartment AS sd
 
159
                WHERE d.parent_department = sd.id
 
160
)
 
161
SELECT * FROM subdepartment ORDER BY name;
 
162
 root_name | id | parent_department | name 
 
163
-----------+----+-------------------+------
 
164
 A         |  1 |                 0 | A
 
165
 A         |  2 |                 1 | B
 
166
 A         |  3 |                 2 | C
 
167
 A         |  4 |                 2 | D
 
168
 A         |  6 |                 4 | F
 
169
(5 rows)
 
170
 
 
171
-- extract all departments under 'A' with "level" number
 
172
WITH RECURSIVE subdepartment(level, id, parent_department, name) AS
 
173
(
 
174
        -- non recursive term
 
175
        SELECT 1, * FROM department WHERE name = 'A'
 
176
        UNION ALL
 
177
        -- recursive term
 
178
        SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd
 
179
                WHERE d.parent_department = sd.id
 
180
)
 
181
SELECT * FROM subdepartment ORDER BY name;
 
182
 level | id | parent_department | name 
 
183
-------+----+-------------------+------
 
184
     1 |  1 |                 0 | A
 
185
     2 |  2 |                 1 | B
 
186
     3 |  3 |                 2 | C
 
187
     3 |  4 |                 2 | D
 
188
     4 |  6 |                 4 | F
 
189
(5 rows)
 
190
 
 
191
-- extract all departments under 'A' with "level" number.
 
192
-- Only shows level 2 or more
 
193
WITH RECURSIVE subdepartment(level, id, parent_department, name) AS
 
194
(
 
195
        -- non recursive term
 
196
        SELECT 1, * FROM department WHERE name = 'A'
 
197
        UNION ALL
 
198
        -- recursive term
 
199
        SELECT sd.level + 1, d.* FROM department AS d, subdepartment AS sd
 
200
                WHERE d.parent_department = sd.id
 
201
)
 
202
SELECT * FROM subdepartment WHERE level >= 2 ORDER BY name;
 
203
 level | id | parent_department | name 
 
204
-------+----+-------------------+------
 
205
     2 |  2 |                 1 | B
 
206
     3 |  3 |                 2 | C
 
207
     3 |  4 |                 2 | D
 
208
     4 |  6 |                 4 | F
 
209
(4 rows)
 
210
 
 
211
-- "RECURSIVE" is ignored if the query has no self-reference
 
212
WITH RECURSIVE subdepartment AS
 
213
(
 
214
        -- note lack of recursive UNION structure
 
215
        SELECT * FROM department WHERE name = 'A'
 
216
)
 
217
SELECT * FROM subdepartment ORDER BY name;
 
218
 id | parent_department | name 
 
219
----+-------------------+------
 
220
  1 |                 0 | A
 
221
(1 row)
 
222
 
 
223
-- inside subqueries
 
224
SELECT count(*) FROM (
 
225
    WITH RECURSIVE t(n) AS (
 
226
        SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 500
 
227
    )
 
228
    SELECT * FROM t) AS t WHERE n < (
 
229
        SELECT count(*) FROM (
 
230
            WITH RECURSIVE t(n) AS (
 
231
                   SELECT 1 UNION ALL SELECT n + 1 FROM t WHERE n < 100
 
232
                )
 
233
            SELECT * FROM t WHERE n < 50000
 
234
         ) AS t WHERE n < 100);
 
235
 count 
 
236
-------
 
237
    98
 
238
(1 row)
 
239
 
 
240
-- use same CTE twice at different subquery levels
 
241
WITH q1(x,y) AS (
 
242
    SELECT hundred, sum(ten) FROM tenk1 GROUP BY hundred
 
243
  )
 
244
SELECT count(*) FROM q1 WHERE y > (SELECT sum(y)/100 FROM q1 qsub);
 
245
 count 
 
246
-------
 
247
    50
 
248
(1 row)
 
249
 
 
250
-- via a VIEW
 
251
CREATE TEMPORARY VIEW vsubdepartment AS
 
252
        WITH RECURSIVE subdepartment AS
 
253
        (
 
254
                 -- non recursive term
 
255
                SELECT * FROM department WHERE name = 'A'
 
256
                UNION ALL
 
257
                -- recursive term
 
258
                SELECT d.* FROM department AS d, subdepartment AS sd
 
259
                        WHERE d.parent_department = sd.id
 
260
        )
 
261
        SELECT * FROM subdepartment;
 
262
SELECT * FROM vsubdepartment ORDER BY name;
 
263
 id | parent_department | name 
 
264
----+-------------------+------
 
265
  1 |                 0 | A
 
266
  2 |                 1 | B
 
267
  3 |                 2 | C
 
268
  4 |                 2 | D
 
269
  6 |                 4 | F
 
270
(5 rows)
 
271
 
 
272
-- Check reverse listing
 
273
SELECT pg_get_viewdef('vsubdepartment'::regclass);
 
274
                                                                                                                                                                                    pg_get_viewdef                                                                                                                                                                                     
 
275
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 
276
 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;
 
277
(1 row)
 
278
 
 
279
SELECT pg_get_viewdef('vsubdepartment'::regclass, true);
 
280
                                    pg_get_viewdef                                    
 
281
--------------------------------------------------------------------------------------
 
282
  WITH RECURSIVE subdepartment AS (                                                  +
 
283
                  SELECT department.id, department.parent_department, 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
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "tree_pkey" for table "tree"
 
401
INSERT INTO tree
 
402
VALUES (1, NULL), (2, 1), (3,1), (4,2), (5,2), (6,2), (7,3), (8,3),
 
403
       (9,4), (10,4), (11,7), (12,7), (13,7), (14, 9), (15,11), (16,11);
 
404
--
 
405
-- get all paths from "second level" nodes to leaf nodes
 
406
--
 
407
WITH RECURSIVE t(id, path) AS (
 
408
    VALUES(1,ARRAY[]::integer[])
 
409
UNION ALL
 
410
    SELECT tree.id, t.path || tree.id
 
411
    FROM tree JOIN t ON (tree.parent_id = t.id)
 
412
)
 
413
SELECT t1.*, t2.* FROM t AS t1 JOIN t AS t2 ON
 
414
        (t1.path[1] = t2.path[1] AND
 
415
        array_upper(t1.path,1) = 1 AND
 
416
        array_upper(t2.path,1) > 1)
 
417
        ORDER BY t1.id, t2.id;
 
418
 id | path | id |    path     
 
419
----+------+----+-------------
 
420
  2 | {2}  |  4 | {2,4}
 
421
  2 | {2}  |  5 | {2,5}
 
422
  2 | {2}  |  6 | {2,6}
 
423
  2 | {2}  |  9 | {2,4,9}
 
424
  2 | {2}  | 10 | {2,4,10}
 
425
  2 | {2}  | 14 | {2,4,9,14}
 
426
  3 | {3}  |  7 | {3,7}
 
427
  3 | {3}  |  8 | {3,8}
 
428
  3 | {3}  | 11 | {3,7,11}
 
429
  3 | {3}  | 12 | {3,7,12}
 
430
  3 | {3}  | 13 | {3,7,13}
 
431
  3 | {3}  | 15 | {3,7,11,15}
 
432
  3 | {3}  | 16 | {3,7,11,16}
 
433
(13 rows)
 
434
 
 
435
-- just count 'em
 
436
WITH RECURSIVE t(id, path) AS (
 
437
    VALUES(1,ARRAY[]::integer[])
 
438
UNION ALL
 
439
    SELECT tree.id, t.path || tree.id
 
440
    FROM tree JOIN t ON (tree.parent_id = t.id)
 
441
)
 
442
SELECT t1.id, count(t2.*) FROM t AS t1 JOIN t AS t2 ON
 
443
        (t1.path[1] = t2.path[1] AND
 
444
        array_upper(t1.path,1) = 1 AND
 
445
        array_upper(t2.path,1) > 1)
 
446
        GROUP BY t1.id
 
447
        ORDER BY t1.id;
 
448
 id | count 
 
449
----+-------
 
450
  2 |     6
 
451
  3 |     7
 
452
(2 rows)
 
453
 
 
454
-- this variant tickled a whole-row-variable bug in 8.4devel
 
455
WITH RECURSIVE t(id, path) AS (
 
456
    VALUES(1,ARRAY[]::integer[])
 
457
UNION ALL
 
458
    SELECT tree.id, t.path || tree.id
 
459
    FROM tree JOIN t ON (tree.parent_id = t.id)
 
460
)
 
461
SELECT t1.id, t2.path, t2 FROM t AS t1 JOIN t AS t2 ON
 
462
(t1.id=t2.id);
 
463
 id |    path     |         t2         
 
464
----+-------------+--------------------
 
465
  1 | {}          | (1,{})
 
466
  2 | {2}         | (2,{2})
 
467
  3 | {3}         | (3,{3})
 
468
  4 | {2,4}       | (4,"{2,4}")
 
469
  5 | {2,5}       | (5,"{2,5}")
 
470
  6 | {2,6}       | (6,"{2,6}")
 
471
  7 | {3,7}       | (7,"{3,7}")
 
472
  8 | {3,8}       | (8,"{3,8}")
 
473
  9 | {2,4,9}     | (9,"{2,4,9}")
 
474
 10 | {2,4,10}    | (10,"{2,4,10}")
 
475
 11 | {3,7,11}    | (11,"{3,7,11}")
 
476
 12 | {3,7,12}    | (12,"{3,7,12}")
 
477
 13 | {3,7,13}    | (13,"{3,7,13}")
 
478
 14 | {2,4,9,14}  | (14,"{2,4,9,14}")
 
479
 15 | {3,7,11,15} | (15,"{3,7,11,15}")
 
480
 16 | {3,7,11,16} | (16,"{3,7,11,16}")
 
481
(16 rows)
 
482
 
 
483
--
 
484
-- test cycle detection
 
485
--
 
486
create temp table graph( f int, t int, label text );
 
487
insert into graph values
 
488
        (1, 2, 'arc 1 -> 2'),
 
489
        (1, 3, 'arc 1 -> 3'),
 
490
        (2, 3, 'arc 2 -> 3'),
 
491
        (1, 4, 'arc 1 -> 4'),
 
492
        (4, 5, 'arc 4 -> 5'),
 
493
        (5, 1, 'arc 5 -> 1');
 
494
with recursive search_graph(f, t, label, path, cycle) as (
 
495
        select *, array[row(g.f, g.t)], false from graph g
 
496
        union all
 
497
        select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
 
498
        from graph g, search_graph sg
 
499
        where g.f = sg.t and not cycle
 
500
)
 
501
select * from search_graph;
 
502
 f | t |   label    |                   path                    | cycle 
 
503
---+---+------------+-------------------------------------------+-------
 
504
 1 | 2 | arc 1 -> 2 | {"(1,2)"}                                 | f
 
505
 1 | 3 | arc 1 -> 3 | {"(1,3)"}                                 | f
 
506
 2 | 3 | arc 2 -> 3 | {"(2,3)"}                                 | f
 
507
 1 | 4 | arc 1 -> 4 | {"(1,4)"}                                 | f
 
508
 4 | 5 | arc 4 -> 5 | {"(4,5)"}                                 | f
 
509
 5 | 1 | arc 5 -> 1 | {"(5,1)"}                                 | f
 
510
 1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"}                         | f
 
511
 1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"}                         | f
 
512
 1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"}                         | f
 
513
 2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}                         | f
 
514
 4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}                         | f
 
515
 5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"}                         | f
 
516
 1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"}                 | f
 
517
 1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"}                 | f
 
518
 1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"}                 | f
 
519
 2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"}                 | f
 
520
 4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"}                 | f
 
521
 5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"}                 | f
 
522
 1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"}         | f
 
523
 1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"}         | f
 
524
 1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"}         | t
 
525
 2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"}         | f
 
526
 4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"}         | t
 
527
 5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"}         | t
 
528
 2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
 
529
(25 rows)
 
530
 
 
531
-- ordering by the path column has same effect as SEARCH DEPTH FIRST
 
532
with recursive search_graph(f, t, label, path, cycle) as (
 
533
        select *, array[row(g.f, g.t)], false from graph g
 
534
        union all
 
535
        select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
 
536
        from graph g, search_graph sg
 
537
        where g.f = sg.t and not cycle
 
538
)
 
539
select * from search_graph order by path;
 
540
 f | t |   label    |                   path                    | cycle 
 
541
---+---+------------+-------------------------------------------+-------
 
542
 1 | 2 | arc 1 -> 2 | {"(1,2)"}                                 | f
 
543
 2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"}                         | f
 
544
 1 | 3 | arc 1 -> 3 | {"(1,3)"}                                 | f
 
545
 1 | 4 | arc 1 -> 4 | {"(1,4)"}                                 | f
 
546
 4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"}                         | f
 
547
 5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"}                 | f
 
548
 1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"}         | f
 
549
 2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
 
550
 1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"}         | f
 
551
 1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"}         | t
 
552
 2 | 3 | arc 2 -> 3 | {"(2,3)"}                                 | f
 
553
 4 | 5 | arc 4 -> 5 | {"(4,5)"}                                 | f
 
554
 5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"}                         | f
 
555
 1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"}                 | f
 
556
 2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"}         | f
 
557
 1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"}                 | f
 
558
 1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"}                 | f
 
559
 4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"}         | t
 
560
 5 | 1 | arc 5 -> 1 | {"(5,1)"}                                 | f
 
561
 1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"}                         | f
 
562
 2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"}                 | f
 
563
 1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"}                         | f
 
564
 1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"}                         | f
 
565
 4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"}                 | f
 
566
 5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"}         | t
 
567
(25 rows)
 
568
 
 
569
--
 
570
-- test multiple WITH queries
 
571
--
 
572
WITH RECURSIVE
 
573
  y (id) AS (VALUES (1)),
 
574
  x (id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5)
 
575
SELECT * FROM x;
 
576
 id 
 
577
----
 
578
  1
 
579
  2
 
580
  3
 
581
  4
 
582
  5
 
583
(5 rows)
 
584
 
 
585
-- forward reference OK
 
586
WITH RECURSIVE
 
587
    x(id) AS (SELECT * FROM y UNION ALL SELECT id+1 FROM x WHERE id < 5),
 
588
    y(id) AS (values (1))
 
589
 SELECT * FROM x;
 
590
 id 
 
591
----
 
592
  1
 
593
  2
 
594
  3
 
595
  4
 
596
  5
 
597
(5 rows)
 
598
 
 
599
WITH RECURSIVE
 
600
   x(id) AS
 
601
     (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5),
 
602
   y(id) AS
 
603
     (VALUES (1) UNION ALL SELECT id+1 FROM y WHERE id < 10)
 
604
 SELECT y.*, x.* FROM y LEFT JOIN x USING (id);
 
605
 id | id 
 
606
----+----
 
607
  1 |  1
 
608
  2 |  2
 
609
  3 |  3
 
610
  4 |  4
 
611
  5 |  5
 
612
  6 |   
 
613
  7 |   
 
614
  8 |   
 
615
  9 |   
 
616
 10 |   
 
617
(10 rows)
 
618
 
 
619
WITH RECURSIVE
 
620
   x(id) AS
 
621
     (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 5),
 
622
   y(id) AS
 
623
     (VALUES (1) UNION ALL SELECT id+1 FROM x WHERE id < 10)
 
624
 SELECT y.*, x.* FROM y LEFT JOIN x USING (id);
 
625
 id | id 
 
626
----+----
 
627
  1 |  1
 
628
  2 |  2
 
629
  3 |  3
 
630
  4 |  4
 
631
  5 |  5
 
632
  6 |   
 
633
(6 rows)
 
634
 
 
635
WITH RECURSIVE
 
636
   x(id) AS
 
637
     (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ),
 
638
   y(id) AS
 
639
     (SELECT * FROM x UNION ALL SELECT * FROM x),
 
640
   z(id) AS
 
641
     (SELECT * FROM x UNION ALL SELECT id+1 FROM z WHERE id < 10)
 
642
 SELECT * FROM z;
 
643
 id 
 
644
----
 
645
  1
 
646
  2
 
647
  3
 
648
  2
 
649
  3
 
650
  4
 
651
  3
 
652
  4
 
653
  5
 
654
  4
 
655
  5
 
656
  6
 
657
  5
 
658
  6
 
659
  7
 
660
  6
 
661
  7
 
662
  8
 
663
  7
 
664
  8
 
665
  9
 
666
  8
 
667
  9
 
668
 10
 
669
  9
 
670
 10
 
671
 10
 
672
(27 rows)
 
673
 
 
674
WITH RECURSIVE
 
675
   x(id) AS
 
676
     (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 3 ),
 
677
   y(id) AS
 
678
     (SELECT * FROM x UNION ALL SELECT * FROM x),
 
679
   z(id) AS
 
680
     (SELECT * FROM y UNION ALL SELECT id+1 FROM z WHERE id < 10)
 
681
 SELECT * FROM z;
 
682
 id 
 
683
----
 
684
  1
 
685
  2
 
686
  3
 
687
  1
 
688
  2
 
689
  3
 
690
  2
 
691
  3
 
692
  4
 
693
  2
 
694
  3
 
695
  4
 
696
  3
 
697
  4
 
698
  5
 
699
  3
 
700
  4
 
701
  5
 
702
  4
 
703
  5
 
704
  6
 
705
  4
 
706
  5
 
707
  6
 
708
  5
 
709
  6
 
710
  7
 
711
  5
 
712
  6
 
713
  7
 
714
  6
 
715
  7
 
716
  8
 
717
  6
 
718
  7
 
719
  8
 
720
  7
 
721
  8
 
722
  9
 
723
  7
 
724
  8
 
725
  9
 
726
  8
 
727
  9
 
728
 10
 
729
  8
 
730
  9
 
731
 10
 
732
  9
 
733
 10
 
734
  9
 
735
 10
 
736
 10
 
737
 10
 
738
(54 rows)
 
739
 
 
740
--
 
741
-- Test WITH attached to a data-modifying statement
 
742
--
 
743
CREATE TEMPORARY TABLE y (a INTEGER);
 
744
INSERT INTO y SELECT generate_series(1, 10);
 
745
WITH t AS (
 
746
        SELECT a FROM y
 
747
)
 
748
INSERT INTO y
 
749
SELECT a+20 FROM t RETURNING *;
 
750
 a  
 
751
----
 
752
 21
 
753
 22
 
754
 23
 
755
 24
 
756
 25
 
757
 26
 
758
 27
 
759
 28
 
760
 29
 
761
 30
 
762
(10 rows)
 
763
 
 
764
SELECT * FROM y;
 
765
 a  
 
766
----
 
767
  1
 
768
  2
 
769
  3
 
770
  4
 
771
  5
 
772
  6
 
773
  7
 
774
  8
 
775
  9
 
776
 10
 
777
 21
 
778
 22
 
779
 23
 
780
 24
 
781
 25
 
782
 26
 
783
 27
 
784
 28
 
785
 29
 
786
 30
 
787
(20 rows)
 
788
 
 
789
WITH t AS (
 
790
        SELECT a FROM y
 
791
)
 
792
UPDATE y SET a = y.a-10 FROM t WHERE y.a > 20 AND t.a = y.a RETURNING y.a;
 
793
 a  
 
794
----
 
795
 11
 
796
 12
 
797
 13
 
798
 14
 
799
 15
 
800
 16
 
801
 17
 
802
 18
 
803
 19
 
804
 20
 
805
(10 rows)
 
806
 
 
807
SELECT * FROM y;
 
808
 a  
 
809
----
 
810
  1
 
811
  2
 
812
  3
 
813
  4
 
814
  5
 
815
  6
 
816
  7
 
817
  8
 
818
  9
 
819
 10
 
820
 11
 
821
 12
 
822
 13
 
823
 14
 
824
 15
 
825
 16
 
826
 17
 
827
 18
 
828
 19
 
829
 20
 
830
(20 rows)
 
831
 
 
832
WITH RECURSIVE t(a) AS (
 
833
        SELECT 11
 
834
        UNION ALL
 
835
        SELECT a+1 FROM t WHERE a < 50
 
836
)
 
837
DELETE FROM y USING t WHERE t.a = y.a RETURNING y.a;
 
838
 a  
 
839
----
 
840
 11
 
841
 12
 
842
 13
 
843
 14
 
844
 15
 
845
 16
 
846
 17
 
847
 18
 
848
 19
 
849
 20
 
850
(10 rows)
 
851
 
 
852
SELECT * FROM y;
 
853
 a  
 
854
----
 
855
  1
 
856
  2
 
857
  3
 
858
  4
 
859
  5
 
860
  6
 
861
  7
 
862
  8
 
863
  9
 
864
 10
 
865
(10 rows)
 
866
 
 
867
DROP TABLE y;
 
868
--
 
869
-- error cases
 
870
--
 
871
-- INTERSECT
 
872
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x)
 
873
        SELECT * FROM x;
 
874
ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
 
875
LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT SELECT n+1 FROM x...
 
876
                       ^
 
877
WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FROM x)
 
878
        SELECT * FROM x;
 
879
ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
 
880
LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 INTERSECT ALL SELECT n+1 FR...
 
881
                       ^
 
882
-- EXCEPT
 
883
WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x)
 
884
        SELECT * FROM x;
 
885
ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
 
886
LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT SELECT n+1 FROM x)
 
887
                       ^
 
888
WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM x)
 
889
        SELECT * FROM x;
 
890
ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
 
891
LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 EXCEPT ALL SELECT n+1 FROM ...
 
892
                       ^
 
893
-- no non-recursive term
 
894
WITH RECURSIVE x(n) AS (SELECT n FROM x)
 
895
        SELECT * FROM x;
 
896
ERROR:  recursive query "x" does not have the form non-recursive-term UNION [ALL] recursive-term
 
897
LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x)
 
898
                       ^
 
899
-- recursive term in the left hand side (strictly speaking, should allow this)
 
900
WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
 
901
        SELECT * FROM x;
 
902
ERROR:  recursive reference to query "x" must not appear within its non-recursive term
 
903
LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
 
904
                                              ^
 
905
CREATE TEMPORARY TABLE y (a INTEGER);
 
906
INSERT INTO y SELECT generate_series(1, 10);
 
907
-- LEFT JOIN
 
908
WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
 
909
        UNION ALL
 
910
        SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10)
 
911
SELECT * FROM x;
 
912
ERROR:  recursive reference to query "x" must not appear within an outer join
 
913
LINE 3:  SELECT x.n+1 FROM y LEFT JOIN x ON x.n = y.a WHERE n < 10)
 
914
                                       ^
 
915
-- RIGHT JOIN
 
916
WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
 
917
        UNION ALL
 
918
        SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10)
 
919
SELECT * FROM x;
 
920
ERROR:  recursive reference to query "x" must not appear within an outer join
 
921
LINE 3:  SELECT x.n+1 FROM x RIGHT JOIN y ON x.n = y.a WHERE n < 10)
 
922
                           ^
 
923
-- FULL JOIN
 
924
WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
 
925
        UNION ALL
 
926
        SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10)
 
927
SELECT * FROM x;
 
928
ERROR:  recursive reference to query "x" must not appear within an outer join
 
929
LINE 3:  SELECT x.n+1 FROM x FULL JOIN y ON x.n = y.a WHERE n < 10)
 
930
                           ^
 
931
-- subquery
 
932
WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x
 
933
                          WHERE n IN (SELECT * FROM x))
 
934
  SELECT * FROM x;
 
935
ERROR:  recursive reference to query "x" must not appear within a subquery
 
936
LINE 2:                           WHERE n IN (SELECT * FROM x))
 
937
                                                            ^
 
938
-- aggregate functions
 
939
WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) FROM x)
 
940
  SELECT * FROM x;
 
941
ERROR:  aggregate functions not allowed in a recursive query's recursive term
 
942
LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT count(*) F...
 
943
                                                          ^
 
944
WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FROM x)
 
945
  SELECT * FROM x;
 
946
ERROR:  aggregate functions not allowed in a recursive query's recursive term
 
947
LINE 1: WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT sum(n) FRO...
 
948
                                                          ^
 
949
-- ORDER BY
 
950
WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1)
 
951
  SELECT * FROM x;
 
952
ERROR:  ORDER BY in a recursive query is not implemented
 
953
LINE 1: ...VE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x ORDER BY 1)
 
954
                                                                     ^
 
955
-- LIMIT/OFFSET
 
956
WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1)
 
957
  SELECT * FROM x;
 
958
ERROR:  OFFSET in a recursive query is not implemented
 
959
LINE 1: ... AS (SELECT 1 UNION ALL SELECT n+1 FROM x LIMIT 10 OFFSET 1)
 
960
                                                                     ^
 
961
-- FOR UPDATE
 
962
WITH RECURSIVE x(n) AS (SELECT 1 UNION ALL SELECT n+1 FROM x FOR UPDATE)
 
963
  SELECT * FROM x;
 
964
ERROR:  FOR UPDATE/SHARE in a recursive query is not implemented
 
965
-- target list has a recursive query name
 
966
WITH RECURSIVE x(id) AS (values (1)
 
967
    UNION ALL
 
968
    SELECT (SELECT * FROM x) FROM x WHERE id < 5
 
969
) SELECT * FROM x;
 
970
ERROR:  recursive reference to query "x" must not appear within a subquery
 
971
LINE 3:     SELECT (SELECT * FROM x) FROM x WHERE id < 5
 
972
                                  ^
 
973
-- mutual recursive query (not implemented)
 
974
WITH RECURSIVE
 
975
  x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id < 5),
 
976
  y (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM x WHERE id < 5)
 
977
SELECT * FROM x;
 
978
ERROR:  mutual recursion between WITH items is not implemented
 
979
LINE 2:   x (id) AS (SELECT 1 UNION ALL SELECT id+1 FROM y WHERE id ...
 
980
          ^
 
981
-- non-linear recursion is not allowed
 
982
WITH RECURSIVE foo(i) AS
 
983
    (values (1)
 
984
    UNION ALL
 
985
       (SELECT i+1 FROM foo WHERE i < 10
 
986
          UNION ALL
 
987
       SELECT i+1 FROM foo WHERE i < 5)
 
988
) SELECT * FROM foo;
 
989
ERROR:  recursive reference to query "foo" must not appear more than once
 
990
LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
 
991
                               ^
 
992
WITH RECURSIVE foo(i) AS
 
993
    (values (1)
 
994
    UNION ALL
 
995
           SELECT * FROM
 
996
       (SELECT i+1 FROM foo WHERE i < 10
 
997
          UNION ALL
 
998
       SELECT i+1 FROM foo WHERE i < 5) AS t
 
999
) SELECT * FROM foo;
 
1000
ERROR:  recursive reference to query "foo" must not appear more than once
 
1001
LINE 7:        SELECT i+1 FROM foo WHERE i < 5) AS t
 
1002
                               ^
 
1003
WITH RECURSIVE foo(i) AS
 
1004
    (values (1)
 
1005
    UNION ALL
 
1006
       (SELECT i+1 FROM foo WHERE i < 10
 
1007
          EXCEPT
 
1008
       SELECT i+1 FROM foo WHERE i < 5)
 
1009
) SELECT * FROM foo;
 
1010
ERROR:  recursive reference to query "foo" must not appear within EXCEPT
 
1011
LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
 
1012
                               ^
 
1013
WITH RECURSIVE foo(i) AS
 
1014
    (values (1)
 
1015
    UNION ALL
 
1016
       (SELECT i+1 FROM foo WHERE i < 10
 
1017
          INTERSECT
 
1018
       SELECT i+1 FROM foo WHERE i < 5)
 
1019
) SELECT * FROM foo;
 
1020
ERROR:  recursive reference to query "foo" must not appear more than once
 
1021
LINE 6:        SELECT i+1 FROM foo WHERE i < 5)
 
1022
                               ^
 
1023
-- Wrong type induced from non-recursive term
 
1024
WITH RECURSIVE foo(i) AS
 
1025
   (SELECT i FROM (VALUES(1),(2)) t(i)
 
1026
   UNION ALL
 
1027
   SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
 
1028
SELECT * FROM foo;
 
1029
ERROR:  recursive query "foo" column 1 has type integer in non-recursive term but type numeric overall
 
1030
LINE 2:    (SELECT i FROM (VALUES(1),(2)) t(i)
 
1031
                   ^
 
1032
HINT:  Cast the output of the non-recursive term to the correct type.
 
1033
-- rejects different typmod, too (should we allow this?)
 
1034
WITH RECURSIVE foo(i) AS
 
1035
   (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
 
1036
   UNION ALL
 
1037
   SELECT (i+1)::numeric(10,0) FROM foo WHERE i < 10)
 
1038
SELECT * FROM foo;
 
1039
ERROR:  recursive query "foo" column 1 has type numeric(3,0) in non-recursive term but type numeric overall
 
1040
LINE 2:    (SELECT i::numeric(3,0) FROM (VALUES(1),(2)) t(i)
 
1041
                   ^
 
1042
HINT:  Cast the output of the non-recursive term to the correct type.
 
1043
-- disallow OLD/NEW reference in CTE
 
1044
CREATE TEMPORARY TABLE x (n integer);
 
1045
CREATE RULE r2 AS ON UPDATE TO x DO INSTEAD
 
1046
    WITH t AS (SELECT OLD.*) UPDATE y SET a = t.n FROM t;
 
1047
ERROR:  cannot refer to OLD within WITH query
 
1048
--
 
1049
-- test for bug #4902
 
1050
--
 
1051
with cte(foo) as ( values(42) ) values((select foo from cte));
 
1052
 column1 
 
1053
---------
 
1054
      42
 
1055
(1 row)
 
1056
 
 
1057
with cte(foo) as ( select 42 ) select * from ((select foo from cte)) q;
 
1058
 foo 
 
1059
-----
 
1060
  42
 
1061
(1 row)
 
1062
 
 
1063
-- test CTE referencing an outer-level variable (to see that changed-parameter
 
1064
-- signaling still works properly after fixing this bug)
 
1065
select ( with cte(foo) as ( values(f1) )
 
1066
         select (select foo from cte) )
 
1067
from int4_tbl;
 
1068
  ?column?   
 
1069
-------------
 
1070
           0
 
1071
      123456
 
1072
     -123456
 
1073
  2147483647
 
1074
 -2147483647
 
1075
(5 rows)
 
1076
 
 
1077
select ( with cte(foo) as ( values(f1) )
 
1078
          values((select foo from cte)) )
 
1079
from int4_tbl;
 
1080
  ?column?   
 
1081
-------------
 
1082
           0
 
1083
      123456
 
1084
     -123456
 
1085
  2147483647
 
1086
 -2147483647
 
1087
(5 rows)
 
1088
 
 
1089
--
 
1090
-- test for nested-recursive-WITH bug
 
1091
--
 
1092
WITH RECURSIVE t(j) AS (
 
1093
    WITH RECURSIVE s(i) AS (
 
1094
        VALUES (1)
 
1095
        UNION ALL
 
1096
        SELECT i+1 FROM s WHERE i < 10
 
1097
    )
 
1098
    SELECT i FROM s
 
1099
    UNION ALL
 
1100
    SELECT j+1 FROM t WHERE j < 10
 
1101
)
 
1102
SELECT * FROM t;
 
1103
 j  
 
1104
----
 
1105
  1
 
1106
  2
 
1107
  3
 
1108
  4
 
1109
  5
 
1110
  6
 
1111
  7
 
1112
  8
 
1113
  9
 
1114
 10
 
1115
  2
 
1116
  3
 
1117
  4
 
1118
  5
 
1119
  6
 
1120
  7
 
1121
  8
 
1122
  9
 
1123
 10
 
1124
  3
 
1125
  4
 
1126
  5
 
1127
  6
 
1128
  7
 
1129
  8
 
1130
  9
 
1131
 10
 
1132
  4
 
1133
  5
 
1134
  6
 
1135
  7
 
1136
  8
 
1137
  9
 
1138
 10
 
1139
  5
 
1140
  6
 
1141
  7
 
1142
  8
 
1143
  9
 
1144
 10
 
1145
  6
 
1146
  7
 
1147
  8
 
1148
  9
 
1149
 10
 
1150
  7
 
1151
  8
 
1152
  9
 
1153
 10
 
1154
  8
 
1155
  9
 
1156
 10
 
1157
  9
 
1158
 10
 
1159
 10
 
1160
(55 rows)
 
1161
 
 
1162
--
 
1163
-- Data-modifying statements in WITH
 
1164
--
 
1165
-- INSERT ... RETURNING
 
1166
WITH t AS (
 
1167
    INSERT INTO y
 
1168
    VALUES
 
1169
        (11),
 
1170
        (12),
 
1171
        (13),
 
1172
        (14),
 
1173
        (15),
 
1174
        (16),
 
1175
        (17),
 
1176
        (18),
 
1177
        (19),
 
1178
        (20)
 
1179
    RETURNING *
 
1180
)
 
1181
SELECT * FROM t;
 
1182
 a  
 
1183
----
 
1184
 11
 
1185
 12
 
1186
 13
 
1187
 14
 
1188
 15
 
1189
 16
 
1190
 17
 
1191
 18
 
1192
 19
 
1193
 20
 
1194
(10 rows)
 
1195
 
 
1196
SELECT * FROM y;
 
1197
 a  
 
1198
----
 
1199
  1
 
1200
  2
 
1201
  3
 
1202
  4
 
1203
  5
 
1204
  6
 
1205
  7
 
1206
  8
 
1207
  9
 
1208
 10
 
1209
 11
 
1210
 12
 
1211
 13
 
1212
 14
 
1213
 15
 
1214
 16
 
1215
 17
 
1216
 18
 
1217
 19
 
1218
 20
 
1219
(20 rows)
 
1220
 
 
1221
-- UPDATE ... RETURNING
 
1222
WITH t AS (
 
1223
    UPDATE y
 
1224
    SET a=a+1
 
1225
    RETURNING *
 
1226
)
 
1227
SELECT * FROM t;
 
1228
 a  
 
1229
----
 
1230
  2
 
1231
  3
 
1232
  4
 
1233
  5
 
1234
  6
 
1235
  7
 
1236
  8
 
1237
  9
 
1238
 10
 
1239
 11
 
1240
 12
 
1241
 13
 
1242
 14
 
1243
 15
 
1244
 16
 
1245
 17
 
1246
 18
 
1247
 19
 
1248
 20
 
1249
 21
 
1250
(20 rows)
 
1251
 
 
1252
SELECT * FROM y;
 
1253
 a  
 
1254
----
 
1255
  2
 
1256
  3
 
1257
  4
 
1258
  5
 
1259
  6
 
1260
  7
 
1261
  8
 
1262
  9
 
1263
 10
 
1264
 11
 
1265
 12
 
1266
 13
 
1267
 14
 
1268
 15
 
1269
 16
 
1270
 17
 
1271
 18
 
1272
 19
 
1273
 20
 
1274
 21
 
1275
(20 rows)
 
1276
 
 
1277
-- DELETE ... RETURNING
 
1278
WITH t AS (
 
1279
    DELETE FROM y
 
1280
    WHERE a <= 10
 
1281
    RETURNING *
 
1282
)
 
1283
SELECT * FROM t;
 
1284
 a  
 
1285
----
 
1286
  2
 
1287
  3
 
1288
  4
 
1289
  5
 
1290
  6
 
1291
  7
 
1292
  8
 
1293
  9
 
1294
 10
 
1295
(9 rows)
 
1296
 
 
1297
SELECT * FROM y;
 
1298
 a  
 
1299
----
 
1300
 11
 
1301
 12
 
1302
 13
 
1303
 14
 
1304
 15
 
1305
 16
 
1306
 17
 
1307
 18
 
1308
 19
 
1309
 20
 
1310
 21
 
1311
(11 rows)
 
1312
 
 
1313
-- forward reference
 
1314
WITH RECURSIVE t AS (
 
1315
        INSERT INTO y
 
1316
                SELECT a+5 FROM t2 WHERE a > 5
 
1317
        RETURNING *
 
1318
), t2 AS (
 
1319
        UPDATE y SET a=a-11 RETURNING *
 
1320
)
 
1321
SELECT * FROM t
 
1322
UNION ALL
 
1323
SELECT * FROM t2;
 
1324
 a  
 
1325
----
 
1326
 11
 
1327
 12
 
1328
 13
 
1329
 14
 
1330
 15
 
1331
  0
 
1332
  1
 
1333
  2
 
1334
  3
 
1335
  4
 
1336
  5
 
1337
  6
 
1338
  7
 
1339
  8
 
1340
  9
 
1341
 10
 
1342
(16 rows)
 
1343
 
 
1344
SELECT * FROM y;
 
1345
 a  
 
1346
----
 
1347
  0
 
1348
  1
 
1349
  2
 
1350
  3
 
1351
  4
 
1352
  5
 
1353
  6
 
1354
 11
 
1355
  7
 
1356
 12
 
1357
  8
 
1358
 13
 
1359
  9
 
1360
 14
 
1361
 10
 
1362
 15
 
1363
(16 rows)
 
1364
 
 
1365
-- unconditional DO INSTEAD rule
 
1366
CREATE RULE y_rule AS ON DELETE TO y DO INSTEAD
 
1367
  INSERT INTO y VALUES(42) RETURNING *;
 
1368
WITH t AS (
 
1369
        DELETE FROM y RETURNING *
 
1370
)
 
1371
SELECT * FROM t;
 
1372
 a  
 
1373
----
 
1374
 42
 
1375
(1 row)
 
1376
 
 
1377
SELECT * FROM y;
 
1378
 a  
 
1379
----
 
1380
  0
 
1381
  1
 
1382
  2
 
1383
  3
 
1384
  4
 
1385
  5
 
1386
  6
 
1387
 11
 
1388
  7
 
1389
 12
 
1390
  8
 
1391
 13
 
1392
  9
 
1393
 14
 
1394
 10
 
1395
 15
 
1396
 42
 
1397
(17 rows)
 
1398
 
 
1399
DROP RULE y_rule ON y;
 
1400
-- a truly recursive CTE in the same list
 
1401
WITH RECURSIVE t(a) AS (
 
1402
        SELECT 0
 
1403
                UNION ALL
 
1404
        SELECT a+1 FROM t WHERE a+1 < 5
 
1405
), t2 as (
 
1406
        INSERT INTO y
 
1407
                SELECT * FROM t RETURNING *
 
1408
)
 
1409
SELECT * FROM t2 JOIN y USING (a) ORDER BY a;
 
1410
 a 
 
1411
---
 
1412
 0
 
1413
 1
 
1414
 2
 
1415
 3
 
1416
 4
 
1417
(5 rows)
 
1418
 
 
1419
SELECT * FROM y;
 
1420
 a  
 
1421
----
 
1422
  0
 
1423
  1
 
1424
  2
 
1425
  3
 
1426
  4
 
1427
  5
 
1428
  6
 
1429
 11
 
1430
  7
 
1431
 12
 
1432
  8
 
1433
 13
 
1434
  9
 
1435
 14
 
1436
 10
 
1437
 15
 
1438
 42
 
1439
  0
 
1440
  1
 
1441
  2
 
1442
  3
 
1443
  4
 
1444
(22 rows)
 
1445
 
 
1446
-- data-modifying WITH in a modifying statement
 
1447
WITH t AS (
 
1448
    DELETE FROM y
 
1449
    WHERE a <= 10
 
1450
    RETURNING *
 
1451
)
 
1452
INSERT INTO y SELECT -a FROM t RETURNING *;
 
1453
  a  
 
1454
-----
 
1455
   0
 
1456
  -1
 
1457
  -2
 
1458
  -3
 
1459
  -4
 
1460
  -5
 
1461
  -6
 
1462
  -7
 
1463
  -8
 
1464
  -9
 
1465
 -10
 
1466
   0
 
1467
  -1
 
1468
  -2
 
1469
  -3
 
1470
  -4
 
1471
(16 rows)
 
1472
 
 
1473
SELECT * FROM y;
 
1474
  a  
 
1475
-----
 
1476
  11
 
1477
  12
 
1478
  13
 
1479
  14
 
1480
  15
 
1481
  42
 
1482
   0
 
1483
  -1
 
1484
  -2
 
1485
  -3
 
1486
  -4
 
1487
  -5
 
1488
  -6
 
1489
  -7
 
1490
  -8
 
1491
  -9
 
1492
 -10
 
1493
   0
 
1494
  -1
 
1495
  -2
 
1496
  -3
 
1497
  -4
 
1498
(22 rows)
 
1499
 
 
1500
-- check that WITH query is run to completion even if outer query isn't
 
1501
WITH t AS (
 
1502
    UPDATE y SET a = a * 100 RETURNING *
 
1503
)
 
1504
SELECT * FROM t LIMIT 10;
 
1505
  a   
 
1506
------
 
1507
 1100
 
1508
 1200
 
1509
 1300
 
1510
 1400
 
1511
 1500
 
1512
 4200
 
1513
    0
 
1514
 -100
 
1515
 -200
 
1516
 -300
 
1517
(10 rows)
 
1518
 
 
1519
SELECT * FROM y;
 
1520
   a   
 
1521
-------
 
1522
  1100
 
1523
  1200
 
1524
  1300
 
1525
  1400
 
1526
  1500
 
1527
  4200
 
1528
     0
 
1529
  -100
 
1530
  -200
 
1531
  -300
 
1532
  -400
 
1533
  -500
 
1534
  -600
 
1535
  -700
 
1536
  -800
 
1537
  -900
 
1538
 -1000
 
1539
     0
 
1540
  -100
 
1541
  -200
 
1542
  -300
 
1543
  -400
 
1544
(22 rows)
 
1545
 
 
1546
-- check that run to completion happens in proper ordering
 
1547
TRUNCATE TABLE y;
 
1548
INSERT INTO y SELECT generate_series(1, 3);
 
1549
CREATE TEMPORARY TABLE yy (a INTEGER);
 
1550
WITH RECURSIVE t1 AS (
 
1551
  INSERT INTO y SELECT * FROM y RETURNING *
 
1552
), t2 AS (
 
1553
  INSERT INTO yy SELECT * FROM t1 RETURNING *
 
1554
)
 
1555
SELECT 1;
 
1556
 ?column? 
 
1557
----------
 
1558
        1
 
1559
(1 row)
 
1560
 
 
1561
SELECT * FROM y;
 
1562
 a 
 
1563
---
 
1564
 1
 
1565
 2
 
1566
 3
 
1567
 1
 
1568
 2
 
1569
 3
 
1570
(6 rows)
 
1571
 
 
1572
SELECT * FROM yy;
 
1573
 a 
 
1574
---
 
1575
 1
 
1576
 2
 
1577
 3
 
1578
(3 rows)
 
1579
 
 
1580
WITH RECURSIVE t1 AS (
 
1581
  INSERT INTO yy SELECT * FROM t2 RETURNING *
 
1582
), t2 AS (
 
1583
  INSERT INTO y SELECT * FROM y RETURNING *
 
1584
)
 
1585
SELECT 1;
 
1586
 ?column? 
 
1587
----------
 
1588
        1
 
1589
(1 row)
 
1590
 
 
1591
SELECT * FROM y;
 
1592
 a 
 
1593
---
 
1594
 1
 
1595
 2
 
1596
 3
 
1597
 1
 
1598
 2
 
1599
 3
 
1600
 1
 
1601
 2
 
1602
 3
 
1603
 1
 
1604
 2
 
1605
 3
 
1606
(12 rows)
 
1607
 
 
1608
SELECT * FROM yy;
 
1609
 a 
 
1610
---
 
1611
 1
 
1612
 2
 
1613
 3
 
1614
 1
 
1615
 2
 
1616
 3
 
1617
 1
 
1618
 2
 
1619
 3
 
1620
(9 rows)
 
1621
 
 
1622
-- triggers
 
1623
TRUNCATE TABLE y;
 
1624
INSERT INTO y SELECT generate_series(1, 10);
 
1625
CREATE FUNCTION y_trigger() RETURNS trigger AS $$
 
1626
begin
 
1627
  raise notice 'y_trigger: a = %', new.a;
 
1628
  return new;
 
1629
end;
 
1630
$$ LANGUAGE plpgsql;
 
1631
CREATE TRIGGER y_trig BEFORE INSERT ON y FOR EACH ROW
 
1632
    EXECUTE PROCEDURE y_trigger();
 
1633
WITH t AS (
 
1634
    INSERT INTO y
 
1635
    VALUES
 
1636
        (21),
 
1637
        (22),
 
1638
        (23)
 
1639
    RETURNING *
 
1640
)
 
1641
SELECT * FROM t;
 
1642
NOTICE:  y_trigger: a = 21
 
1643
NOTICE:  y_trigger: a = 22
 
1644
NOTICE:  y_trigger: a = 23
 
1645
 a  
 
1646
----
 
1647
 21
 
1648
 22
 
1649
 23
 
1650
(3 rows)
 
1651
 
 
1652
SELECT * FROM y;
 
1653
 a  
 
1654
----
 
1655
  1
 
1656
  2
 
1657
  3
 
1658
  4
 
1659
  5
 
1660
  6
 
1661
  7
 
1662
  8
 
1663
  9
 
1664
 10
 
1665
 21
 
1666
 22
 
1667
 23
 
1668
(13 rows)
 
1669
 
 
1670
DROP TRIGGER y_trig ON y;
 
1671
CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH ROW
 
1672
    EXECUTE PROCEDURE y_trigger();
 
1673
WITH t AS (
 
1674
    INSERT INTO y
 
1675
    VALUES
 
1676
        (31),
 
1677
        (32),
 
1678
        (33)
 
1679
    RETURNING *
 
1680
)
 
1681
SELECT * FROM t LIMIT 1;
 
1682
NOTICE:  y_trigger: a = 31
 
1683
NOTICE:  y_trigger: a = 32
 
1684
NOTICE:  y_trigger: a = 33
 
1685
 a  
 
1686
----
 
1687
 31
 
1688
(1 row)
 
1689
 
 
1690
SELECT * FROM y;
 
1691
 a  
 
1692
----
 
1693
  1
 
1694
  2
 
1695
  3
 
1696
  4
 
1697
  5
 
1698
  6
 
1699
  7
 
1700
  8
 
1701
  9
 
1702
 10
 
1703
 21
 
1704
 22
 
1705
 23
 
1706
 31
 
1707
 32
 
1708
 33
 
1709
(16 rows)
 
1710
 
 
1711
DROP TRIGGER y_trig ON y;
 
1712
CREATE OR REPLACE FUNCTION y_trigger() RETURNS trigger AS $$
 
1713
begin
 
1714
  raise notice 'y_trigger';
 
1715
  return null;
 
1716
end;
 
1717
$$ LANGUAGE plpgsql;
 
1718
CREATE TRIGGER y_trig AFTER INSERT ON y FOR EACH STATEMENT
 
1719
    EXECUTE PROCEDURE y_trigger();
 
1720
WITH t AS (
 
1721
    INSERT INTO y
 
1722
    VALUES
 
1723
        (41),
 
1724
        (42),
 
1725
        (43)
 
1726
    RETURNING *
 
1727
)
 
1728
SELECT * FROM t;
 
1729
NOTICE:  y_trigger
 
1730
 a  
 
1731
----
 
1732
 41
 
1733
 42
 
1734
 43
 
1735
(3 rows)
 
1736
 
 
1737
SELECT * FROM y;
 
1738
 a  
 
1739
----
 
1740
  1
 
1741
  2
 
1742
  3
 
1743
  4
 
1744
  5
 
1745
  6
 
1746
  7
 
1747
  8
 
1748
  9
 
1749
 10
 
1750
 21
 
1751
 22
 
1752
 23
 
1753
 31
 
1754
 32
 
1755
 33
 
1756
 41
 
1757
 42
 
1758
 43
 
1759
(19 rows)
 
1760
 
 
1761
DROP TRIGGER y_trig ON y;
 
1762
DROP FUNCTION y_trigger();
 
1763
-- error cases
 
1764
-- data-modifying WITH tries to use its own output
 
1765
WITH RECURSIVE t AS (
 
1766
        INSERT INTO y
 
1767
                SELECT * FROM t
 
1768
)
 
1769
VALUES(FALSE);
 
1770
ERROR:  recursive query "t" must not contain data-modifying statements
 
1771
LINE 1: WITH RECURSIVE t AS (
 
1772
                       ^
 
1773
-- no RETURNING in a referenced data-modifying WITH
 
1774
WITH t AS (
 
1775
        INSERT INTO y VALUES(0)
 
1776
)
 
1777
SELECT * FROM t;
 
1778
ERROR:  WITH query "t" does not have a RETURNING clause
 
1779
LINE 4: SELECT * FROM t;
 
1780
                      ^
 
1781
-- data-modifying WITH allowed only at the top level
 
1782
SELECT * FROM (
 
1783
        WITH t AS (UPDATE y SET a=a+1 RETURNING *)
 
1784
        SELECT * FROM t
 
1785
) ss;
 
1786
ERROR:  WITH clause containing a data-modifying statement must be at the top level
 
1787
LINE 2:  WITH t AS (UPDATE y SET a=a+1 RETURNING *)
 
1788
              ^
 
1789
-- most variants of rules aren't allowed
 
1790
CREATE RULE y_rule AS ON INSERT TO y WHERE a=0 DO INSTEAD DELETE FROM y;
 
1791
WITH t AS (
 
1792
        INSERT INTO y VALUES(0)
 
1793
)
 
1794
VALUES(FALSE);
 
1795
ERROR:  conditional DO INSTEAD rules are not supported for data-modifying statements in WITH
 
1796
DROP RULE y_rule ON y;