mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
Adjust cycle detection examples and tests
Adjust the existing cycle detection example and test queries to put the cycle column before the path column. This is mainly because the SQL-standard CYCLE clause puts them in that order, and so if we added that feature that would make the sequence of examples more consistent and easier to follow. Discussion: https://www.postgresql.org/message-id/c5603982-0088-7f14-0caa-fdcd0c837b57@2ndquadrant.com
This commit is contained in:
@ -579,79 +579,79 @@ insert into graph values
|
||||
(1, 4, 'arc 1 -> 4'),
|
||||
(4, 5, 'arc 4 -> 5'),
|
||||
(5, 1, 'arc 5 -> 1');
|
||||
with recursive search_graph(f, t, label, path, cycle) as (
|
||||
select *, array[row(g.f, g.t)], false from graph g
|
||||
with recursive search_graph(f, t, label, is_cycle, path) as (
|
||||
select *, false, array[row(g.f, g.t)] from graph g
|
||||
union all
|
||||
select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
|
||||
select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
|
||||
from graph g, search_graph sg
|
||||
where g.f = sg.t and not cycle
|
||||
where g.f = sg.t and not is_cycle
|
||||
)
|
||||
select * from search_graph;
|
||||
f | t | label | path | cycle
|
||||
---+---+------------+-------------------------------------------+-------
|
||||
1 | 2 | arc 1 -> 2 | {"(1,2)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(1,3)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(2,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(1,4)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(4,5)"} | f
|
||||
5 | 1 | arc 5 -> 1 | {"(5,1)"} | f
|
||||
1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"} | f
|
||||
5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"} | f
|
||||
1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"} | f
|
||||
5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"} | f
|
||||
1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"} | t
|
||||
2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"} | t
|
||||
5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"} | t
|
||||
2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
|
||||
f | t | label | is_cycle | path
|
||||
---+---+------------+----------+-------------------------------------------
|
||||
1 | 2 | arc 1 -> 2 | f | {"(1,2)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(1,3)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(2,3)"}
|
||||
1 | 4 | arc 1 -> 4 | f | {"(1,4)"}
|
||||
4 | 5 | arc 4 -> 5 | f | {"(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | f | {"(5,1)"}
|
||||
1 | 2 | arc 1 -> 2 | f | {"(5,1)","(1,2)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(5,1)","(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | f | {"(5,1)","(1,4)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(1,2)","(2,3)"}
|
||||
4 | 5 | arc 4 -> 5 | f | {"(1,4)","(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | f | {"(4,5)","(5,1)"}
|
||||
1 | 2 | arc 1 -> 2 | f | {"(4,5)","(5,1)","(1,2)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(4,5)","(5,1)","(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | f | {"(4,5)","(5,1)","(1,4)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(5,1)","(1,2)","(2,3)"}
|
||||
4 | 5 | arc 4 -> 5 | f | {"(5,1)","(1,4)","(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | f | {"(1,4)","(4,5)","(5,1)"}
|
||||
1 | 2 | arc 1 -> 2 | f | {"(1,4)","(4,5)","(5,1)","(1,2)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(1,4)","(4,5)","(5,1)","(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | t | {"(1,4)","(4,5)","(5,1)","(1,4)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(4,5)","(5,1)","(1,2)","(2,3)"}
|
||||
4 | 5 | arc 4 -> 5 | t | {"(4,5)","(5,1)","(1,4)","(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | t | {"(5,1)","(1,4)","(4,5)","(5,1)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
|
||||
(25 rows)
|
||||
|
||||
-- ordering by the path column has same effect as SEARCH DEPTH FIRST
|
||||
with recursive search_graph(f, t, label, path, cycle) as (
|
||||
select *, array[row(g.f, g.t)], false from graph g
|
||||
with recursive search_graph(f, t, label, is_cycle, path) as (
|
||||
select *, false, array[row(g.f, g.t)] from graph g
|
||||
union all
|
||||
select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
|
||||
select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
|
||||
from graph g, search_graph sg
|
||||
where g.f = sg.t and not cycle
|
||||
where g.f = sg.t and not is_cycle
|
||||
)
|
||||
select * from search_graph order by path;
|
||||
f | t | label | path | cycle
|
||||
---+---+------------+-------------------------------------------+-------
|
||||
1 | 2 | arc 1 -> 2 | {"(1,2)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(1,2)","(2,3)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(1,4)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(1,4)","(4,5)"} | f
|
||||
5 | 1 | arc 5 -> 1 | {"(1,4)","(4,5)","(5,1)"} | f
|
||||
1 | 2 | arc 1 -> 2 | {"(1,4)","(4,5)","(5,1)","(1,2)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(1,4)","(4,5)","(5,1)","(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(1,4)","(4,5)","(5,1)","(1,4)"} | t
|
||||
2 | 3 | arc 2 -> 3 | {"(2,3)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(4,5)"} | f
|
||||
5 | 1 | arc 5 -> 1 | {"(4,5)","(5,1)"} | f
|
||||
1 | 2 | arc 1 -> 2 | {"(4,5)","(5,1)","(1,2)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(4,5)","(5,1)","(1,2)","(2,3)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(4,5)","(5,1)","(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(4,5)","(5,1)","(1,4)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(4,5)","(5,1)","(1,4)","(4,5)"} | t
|
||||
5 | 1 | arc 5 -> 1 | {"(5,1)"} | f
|
||||
1 | 2 | arc 1 -> 2 | {"(5,1)","(1,2)"} | f
|
||||
2 | 3 | arc 2 -> 3 | {"(5,1)","(1,2)","(2,3)"} | f
|
||||
1 | 3 | arc 1 -> 3 | {"(5,1)","(1,3)"} | f
|
||||
1 | 4 | arc 1 -> 4 | {"(5,1)","(1,4)"} | f
|
||||
4 | 5 | arc 4 -> 5 | {"(5,1)","(1,4)","(4,5)"} | f
|
||||
5 | 1 | arc 5 -> 1 | {"(5,1)","(1,4)","(4,5)","(5,1)"} | t
|
||||
f | t | label | is_cycle | path
|
||||
---+---+------------+----------+-------------------------------------------
|
||||
1 | 2 | arc 1 -> 2 | f | {"(1,2)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(1,2)","(2,3)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | f | {"(1,4)"}
|
||||
4 | 5 | arc 4 -> 5 | f | {"(1,4)","(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | f | {"(1,4)","(4,5)","(5,1)"}
|
||||
1 | 2 | arc 1 -> 2 | f | {"(1,4)","(4,5)","(5,1)","(1,2)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(1,4)","(4,5)","(5,1)","(1,2)","(2,3)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(1,4)","(4,5)","(5,1)","(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | t | {"(1,4)","(4,5)","(5,1)","(1,4)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(2,3)"}
|
||||
4 | 5 | arc 4 -> 5 | f | {"(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | f | {"(4,5)","(5,1)"}
|
||||
1 | 2 | arc 1 -> 2 | f | {"(4,5)","(5,1)","(1,2)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(4,5)","(5,1)","(1,2)","(2,3)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(4,5)","(5,1)","(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | f | {"(4,5)","(5,1)","(1,4)"}
|
||||
4 | 5 | arc 4 -> 5 | t | {"(4,5)","(5,1)","(1,4)","(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | f | {"(5,1)"}
|
||||
1 | 2 | arc 1 -> 2 | f | {"(5,1)","(1,2)"}
|
||||
2 | 3 | arc 2 -> 3 | f | {"(5,1)","(1,2)","(2,3)"}
|
||||
1 | 3 | arc 1 -> 3 | f | {"(5,1)","(1,3)"}
|
||||
1 | 4 | arc 1 -> 4 | f | {"(5,1)","(1,4)"}
|
||||
4 | 5 | arc 4 -> 5 | f | {"(5,1)","(1,4)","(4,5)"}
|
||||
5 | 1 | arc 5 -> 1 | t | {"(5,1)","(1,4)","(4,5)","(5,1)"}
|
||||
(25 rows)
|
||||
|
||||
--
|
||||
|
@ -308,22 +308,22 @@ insert into graph values
|
||||
(4, 5, 'arc 4 -> 5'),
|
||||
(5, 1, 'arc 5 -> 1');
|
||||
|
||||
with recursive search_graph(f, t, label, path, cycle) as (
|
||||
select *, array[row(g.f, g.t)], false from graph g
|
||||
with recursive search_graph(f, t, label, is_cycle, path) as (
|
||||
select *, false, array[row(g.f, g.t)] from graph g
|
||||
union all
|
||||
select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
|
||||
select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
|
||||
from graph g, search_graph sg
|
||||
where g.f = sg.t and not cycle
|
||||
where g.f = sg.t and not is_cycle
|
||||
)
|
||||
select * from search_graph;
|
||||
|
||||
-- ordering by the path column has same effect as SEARCH DEPTH FIRST
|
||||
with recursive search_graph(f, t, label, path, cycle) as (
|
||||
select *, array[row(g.f, g.t)], false from graph g
|
||||
with recursive search_graph(f, t, label, is_cycle, path) as (
|
||||
select *, false, array[row(g.f, g.t)] from graph g
|
||||
union all
|
||||
select g.*, path || row(g.f, g.t), row(g.f, g.t) = any(path)
|
||||
select g.*, row(g.f, g.t) = any(path), path || row(g.f, g.t)
|
||||
from graph g, search_graph sg
|
||||
where g.f = sg.t and not cycle
|
||||
where g.f = sg.t and not is_cycle
|
||||
)
|
||||
select * from search_graph order by path;
|
||||
|
||||
|
Reference in New Issue
Block a user