Can this be done?

Started by Ashley Clarkover 25 years ago4 messagesgeneral
Jump to latest
#1Ashley Clark
aclark@ghoti.org

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

#2Tom Lane
tgl@sss.pgh.pa.us
In reply to: Ashley Clark (#1)
Re: Can this be done?

Ashley Clark <aclark@ghoti.org> writes:

Can I defer constraint checking on unique indexes?

No, not at present. Consider restructuring your UPDATE into sequential
steps so that the intermediate states can't cause index failures. Or
just don't make the index unique...

regards, tom lane

#3Ashley Clark
aclark@ghoti.org
In reply to: Tom Lane (#2)
Re: Can this be done?

* Tom Lane in "Re: [GENERAL] Can this be done?" dated 2000/11/15 00:42
* wrote:

Ashley Clark <aclark@ghoti.org> writes:

Can I defer constraint checking on unique indexes?

No, not at present. Consider restructuring your UPDATE into
sequential steps so that the intermediate states can't cause index
failures. Or just don't make the index unique...

Ok, I can live with that. Is this something that's planned for in the
future?

--
shaky recall

#4igor
igor_kh@mailru.com
In reply to: Ashley Clark (#1)
Dump problem

Hi,

I'm having a problem while dump database (I'm trying
to upgrade from 6.5 to 7.03) . The error message is:

dumpSequence(val_tmp_uid_seq): 0 (!=1) tuples returned by SELECT

Tell me please, what wrong in my database?

Thanks!

Igor.