Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 0622465

Browse files
committed
Add docs and regression test about sorting the output of a recursive query in
depth-first search order. Upon close reading of SQL:2008, it seems that the spec's SEARCH DEPTH FIRST and SEARCH BREADTH FIRST options do not actually guarantee any particular result order: what they do is provide a constructed column that the user can then sort on in the outer query. So this is actually just as much functionality ...
1 parent 1f238e5 commit 0622465

File tree

3 files changed

+61
-2
lines changed

3 files changed

+61
-2
lines changed

doc/src/sgml/queries.sgml

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.49 2008/10/14 00:12:44 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/queries.sgml,v 1.50 2008/10/14 00:41:34 tgl Exp $ -->
22

33
<chapter id="queries">
44
<title>Queries</title>
@@ -1681,6 +1681,15 @@ SELECT * FROM search_graph;
16811681
</para>
16821682
</tip>
16831683

1684+
<tip>
1685+
<para>
1686+
The recursive query evaluation algorithm produces its output in
1687+
breadth-first search order. You can display the results in depth-first
1688+
search order by making the outer query <literal>ORDER BY</> a
1689+
<quote>path</> column constructed in this way.
1690+
</para>
1691+
</tip>
1692+
16841693
<para>
16851694
A helpful trick for testing queries
16861695
when you are not certain if they might loop is to place a <literal>LIMIT</>
@@ -1699,7 +1708,9 @@ SELECT n FROM t LIMIT 100;
16991708
This works because <productname>PostgreSQL</productname>'s implementation
17001709
evaluates only as many rows of a <literal>WITH</> query as are actually
17011710
fetched by the parent query. Using this trick in production is not
1702-
recommended, because other systems might work differently.
1711+
recommended, because other systems might work differently. Also, it
1712+
usually won't work if you make the outer query sort the recursive query's
1713+
results or join them to some other table.
17031714
</para>
17041715

17051716
<para>

src/test/regress/expected/with.out

+38
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,44 @@ select * from search_graph;
499499
2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
500500
(25 rows)
501501

502+
-- ordering by the path column has same effect as SEARCH DEPTH FIRST
503+
with recursive search_graph(f, t, label, path, cycle) as (
504+
select *, array[row(g.f, g.t)], false from graph g
505+
union all
506+
select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
507+
from graph g, search_graph sg
508+
where g.f = sg.t and not cycle
509+
)
510+
select * from search_graph order by path;
511+
f | t | label | path | cycle
512+
---+---+------------+-------------------------------------------+-------
513+
1 | 2 | arc 1 -> 2 | {"(1,2)"} | f
514+
2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"} | f
515+
1 | 3 | arc 1 -> 3 | {"(1,3)"} | f
516+
1 | 4 | arc 1 -> 4 | {"(1,4)"} | f
517+
4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"} | f
518+
5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"} | f
519+
1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"} | f
520+
2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
521+
1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"} | f
522+
1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"} | t
523+
2 | 3 | arc 2 -> 3 | {"(2,3)"} | f
524+
4 | 5 | arc 4 -> 5 | {"(4,5)"} | f
525+
5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"} | f
526+
1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"} | f
527+
2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"} | f
528+
1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"} | f
529+
1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"} | f
530+
4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"} | t
531+
5 | 1 | arc 5 -> 1 | {"(5,1)"} | f
532+
1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"} | f
533+
2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"} | f
534+
1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"} | f
535+
1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"} | f
536+
4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"} | f
537+
5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"} | t
538+
(25 rows)
539+
502540
--
503541
-- test multiple WITH queries
504542
--

src/test/regress/sql/with.sql

+10
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,16 @@ with recursive search_graph(f, t, label, path, cycle) as (
272272
)
273273
select * from search_graph;
274274

275+
-- ordering by the path column has same effect as SEARCH DEPTH FIRST
276+
with recursive search_graph(f, t, label, path, cycle) as (
277+
select *, array[row(g.f, g.t)], false from graph g
278+
union all
279+
select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
280+
from graph g, search_graph sg
281+
where g.f = sg.t and not cycle
282+
)
283+
select * from search_graph order by path;
284+
275285
--
276286
-- test multiple WITH queries
277287
--

0 commit comments

Comments
 (0)