Can this be done?
От | Ashley Clark |
---|---|
Тема | Can this be done? |
Дата | |
Msg-id | 20001114233240.A4434@ghoti.org обсуждение исходный текст |
Ответы |
Re: Can this be done?
Dump problem |
Список | pgsql-general |
I am implementing some set-based trees in a table and I've been writing some functions to manipulate (delete branch, insert node, move branch) them and I've run into a problem with the move_branch function. When I try a select move_tree(13, 25, 0); to move the branch labeled g to be a child of the branch labeled i I get an ERROR: Cannot insert a duplicate key into unique index plan_items_pkey. Why is this happening, I thought that the primary key constraints should be checked AFTER the update is finished, am I wrong? Is there some other way to do this in a single update or will I have to break it up? Can I defer constraint checking on unique indexes? Any help would be appreciated. I'll simplify my structure a little here: create table plan_items ( lft int4 not null, rgt int4 not null, name char(50) not null, primary key (lft), check (lft < rgt), check (lft > 0), check (rgt > 0) ); copy plan_items from stdin; 1 28 a 2 11 b 3 8 e 4 5 j 6 7 k 9 10 f 12 21 c 13 20 g 14 15 l 16 17 m 18 19 n 22 27 d 23 24 h 25 26 i \. And now for the function: create function move_tree(integer, integer, integer) returns integer as ' declare p_node alias for $3; p_parent alias for $4; p_brother alias for $5; droplft plan_items.lft%TYPE; droprgt plan_items.rgt%TYPE; newpos plan_items.lft%TYPE; begin select rgt into newpos from plan_items where lft = p_parent; if p_brother > 0 then select rgt + 1 into newpos from plan_items where lft = p_brother; end if; select lft, rgt into droplft, droprgt from plan_items where lft = p_node; /* reorder nodes in position ??? */ update plan_items set lft = case when lft between droplft and droprgt then lft + newpos - droprgt - 1 when (lft < droplft) and (lft >= newpos) then lft + (droprgt - droplft + 1) when (lft > droprgt) and (lft < newpos) then lft - (droprgt - droplft + 1) else lft end, rgt = case when rgt between droplft and droprgt then rgt + newpos - droprgt - 1 when (rgt < droplft) and (rgt >= newpos) then rgt + (droprgt - droplft + 1) when (rgt > droprgt) and (rgt < newpos) then rgt - (droprgt - droplft + 1) else rgt end; end; ' language 'plpgsql'; -- ashley clark
Вложения
В списке pgsql-general по дате отправления: