Trees: Adjacency List
Сразу скажу, что nested sets для данной задачи не подходит, ибо инсертов будет много - посему adjacency list. Патчить postgresql тоже не хочу - на серверах стоит из rpm binary, и пересобирать везде-везде слишком накладно. Знаю о наличии contrib/ltree, но лексикографические деревья не подходят. Сделал так:
[sql]
create table adjtree(
node_id bigserial primary key,
parent_id bigint default null,
...
);
alter table adjtree add foreign key (parent_id) references adjtree (node_id) on delete cascade;
alter table adjtree add check (parent_id IS NULL or node_id <> parent_id);
[/sql]
...
[sql]
-- Usage:
-- select * from adjtree where node_id in (select * from pathto($1));
-- select * from adjtree where node_id in (select * from descedants($1))
[/sql]
Опыта в написании хранимых процедур у меня немного, так что с благодарностью рассмотрю лучшие варианты.
Сразу скажу, что nested sets для данной задачи не подходит, ибо инсертов будет много - посему adjacency list. Патчить postgresql тоже не хочу - на серверах стоит из rpm binary, и пересобирать везде-везде слишком накладно. Знаю о наличии contrib/ltree, но лексикографические деревья не подходят. Сделал так:
[sql]
create table adjtree(
node_id bigserial primary key,
parent_id bigint default null,
...
);
alter table adjtree add foreign key (parent_id) references adjtree (node_id) on delete cascade;
alter table adjtree add check (parent_id IS NULL or node_id <> parent_id);
[/sql]
...
PHP:
create or replace function pathto(bigint) returns setof bigint as $$
declare
num alias for $1;
parent bigint;
begin
select into parent parent_id from adjtree where node_id=num;
while parent is not null loop
return next parent;
select into parent parent_id from adjtree where node_id=parent;
end loop;
return;
end;
$$ language plpgsql;
create or replace function descedants(bigint) returns setof bigint as $$
declare
r record;
r1 record;
begin
for r in select node_id from adjtree where parent_id=$1 loop
return next r.node_id;
for r1 in select * from descedants(r.node_id) loop
return next r1.descedants;
end loop;
end loop;
return;
end;
$$ language plpgsql;
-- Usage:
-- select * from adjtree where node_id in (select * from pathto($1));
-- select * from adjtree where node_id in (select * from descedants($1))
[/sql]
Опыта в написании хранимых процедур у меня немного, так что с благодарностью рассмотрю лучшие варианты.