CREATE OR REPLACE FUNCTION add_message(int4, int4, int4, varchar) RETURNS int8 AS $$ DECLARE postId ALIAS FOR $1; ownerId ALIAS FOR $2; parentId ALIAS FOR $3; value ALIAS FOR $4; l int8; r int8; half int8; intervalStart int8; intervalEnd int8; parentLeft int8; parentRight int8; newId int8; parentKey record; BEGIN IF parentId <> 0 THEN -- get left and right key from parent SELECT INTO parentKey lft, rgt from "comment" WHERE id = parentId; parentLeft=parentKey.lft; parentRight=parentKey.rgt; ELSE parentLeft=-9223372036854775807; parentRight=9223372036854775807; END IF; -- get right value of the youngest sibling SELECT INTO intervalStart max(rgt) from "comment" WHERE rgt > parentLeft AND rgt < parentRight; -- if the parent has no childs, just use parent left IF intervalStart IS NULL THEN intervalStart:=parentLeft; END IF; -- use parent right as interval end intervalEnd:=parentRight; -- for the first node use precalculated values to avoid calcing with numbers with more than 64 bit IF intervalStart =-9223372036854775807 AND intervalEnd=9223372036854775807 THEN l=-9223372036854775806; r=0; ELSE -- since we only insert after the youngest child we can split the interval -- in rough halfs by using the interval [x+1, x+halfIntervalSize] half:=( intervalEnd-intervalStart)/2; l:= intervalStart+1; r:= intervalStart+half; IF l = intervalStart OR r = intervalEnd OR l = r THEN RAISE EXCEPTION 'Out of keyspace while inserting child to comment %', parentId; END IF; END IF; INSERT INTO "comment" VALUES ( DEFAULT, l, r, value, NOW(), postId, ownerId, FALSE, FALSE); UPDATE "post" SET reply_count=reply_count+1 where id = postId; return currval('comment_id_seq'); END $$ LANGUAGE plpgsql VOLATILE;