Re: [PATCHES] WITH RECURSIVE patch V0.1

Поиск
Список
Период
Сортировка
От Zoltan Boszormenyi
Тема Re: [PATCHES] WITH RECURSIVE patch V0.1
Дата
Msg-id 48309DFA.8080703@cybertec.at
обсуждение исходный текст
Ответ на Re: [PATCHES] WITH RECURSIVE patch V0.1  (David Fetter <david@fetter.org>)
Ответы Re: [PATCHES] WITH RECURSIVE patch V0.1  ("Merlin Moncure" <mmoncure@gmail.com>)
Re: WITH RECURSIVE patch V0.1  (Gregory Stark <stark@enterprisedb.com>)
Re: [PATCHES] WITH RECURSIVE patch V0.1  (Yoshiyuki Asaba <y-asaba@sraoss.co.jp>)
Список pgsql-hackers
David Fetter írta:
> On Sun, May 18, 2008 at 08:51:29PM +0900, Tatsuo Ishii wrote:
>
>> WITH RECURSIVE patch V0.1
>>
>> Here are patches to implement WITH RECURSIVE clause. There are some
>> limitiations and TODO items(see the "Current limitations" section
>> below). Comments are welcome.
>>
>> 1. Credit
>>
>> These patches were developed by Yoshiyuki Asaba (y-asab@sraoss.co.jp)
>> with some discussions with Tatsuo Ishii (ishii@sraoss.co.jp).
>>
>
> This is really great!  Kudos to all who made this happen :)
>
> I tried a bunch of different queries, and so far, only these two
> haven't worked.  Any ideas what I'm doing wrong here?
>
> WITH RECURSIVE t(n) AS (
>     SELECT 1
> UNION ALL
>     SELECT n+1
>     FROM t
>     WHERE n < 100
> )
> SELECT * FROM t;
> ERROR:  cannot extract attribute from empty tuple slot
>
> WITH RECURSIVE t(n) AS (
>     VALUES (1)
> UNION ALL
>     SELECT n+1
>     FROM t
>     WHERE n < 100
> )
> SELECT * FROM t;
> ERROR:  cannot extract attribute from empty tuple slot
>
> Cheers,
> David.
>

Here's a test case attached shamelessly stolen from
http://www.adp-gmbh.ch/ora/sql/connect_by.html

This query (without naming toplevel columns) works:

# with recursive x as (select * from test_connect_by where parent is
null union all select base.* from test_connect_by as base, x where
base.parent = x.child) select * from x;
 parent | child
--------+-------
        |    38
        |    26
        |    18
     18 |    11
     18 |     7
     26 |    13
     26 |     1
     26 |    12
     38 |    15
     38 |    17
     38 |     6
     17 |     9
     17 |     8
     15 |    10
     15 |     5
      5 |     2
      5 |     3
(17 rows)

It even works when I add my "level" column:

# with recursive x(level, parent, child) as (select 1::bigint, * from
test_connect_by where parent is null union all select x.level + 1,
base.* from test_connect_by as base, x where base.parent = x.child)
select * from x;
 level | parent | child
-------+--------+-------
     1 |        |    38
     1 |        |    26
     1 |        |    18
     2 |     18 |    11
     2 |     18 |     7
     2 |     26 |    13
     2 |     26 |     1
     2 |     26 |    12
     2 |     38 |    15
     2 |     38 |    17
     2 |     38 |     6
     3 |     17 |     9
     3 |     17 |     8
     3 |     15 |    10
     3 |     15 |     5
     4 |      5 |     2
     4 |      5 |     3
(17 rows)

But I have a little problem with the output.
If it's not obvious, here is the query tweaked a little below.

# with recursive x(level, parent, child) as (select 1::integer, * from
test_connect_by where parent is null union all select x.level + 1,
base.* from test_connect_by as base, x where base.parent = x.child)
select lpad(' ', 4*level - 1) || child from x;
     ?column?
------------------
    38
    26
    18
        11
        7
        13
        1
        12
        15
        17
        6
            9
            8
            10
            5
                2
                3
(17 rows)

Can we get the rows in tree order, please? I.e. something like this:

     ?column?
------------------
    38
        15
            10
            5
                2
                3
        17
            9
            8
        6
    26
        13
        1
        12
    18
        11
        7
(17 rows)

After all, I didn't specify any ORDER BY clauses in the base, recursive
or the final queries.

Also, it seems there are no infinite recursion detection:

# with recursive x(level, parent, child) as (
    select 1::integer, * from test_connect_by where parent is null
    union all
    select x.level + 1, base.* from test_connect_by as base, x where
base.child = x.child
) select * from x;
... it waits and waits and waits ...

Also, there's another rough edge:

# with recursive x as (select * from test_connect_by where parent is
null) select * from x;
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

Best regards,
Zoltán Böszörményi

--
----------------------------------
Zoltán Böszörményi
Cybertec Schönig & Schönig GmbH
http://www.postgresql.at/

create table test_connect_by (
  parent     integer,
  child      integer,
  constraint uq_tcb unique (child)
);

insert into test_connect_by values ( 5, 2);
insert into test_connect_by values ( 5, 3);

insert into test_connect_by values (18,11);
insert into test_connect_by values (18, 7);

insert into test_connect_by values (17, 9);
insert into test_connect_by values (17, 8);

insert into test_connect_by values (26,13);
insert into test_connect_by values (26, 1);
insert into test_connect_by values (26,12);

insert into test_connect_by values (15,10);
insert into test_connect_by values (15, 5);

insert into test_connect_by values (38,15);
insert into test_connect_by values (38,17);
insert into test_connect_by values (38, 6);

insert into test_connect_by values (null, 38);
insert into test_connect_by values (null, 26);
insert into test_connect_by values (null, 18);


В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Dave Page"
Дата:
Сообщение: Re: odd output in restore mode
Следующее
От: Andrew Dunstan
Дата:
Сообщение: Re: Link requirements creep