Powiedzmy, ze jest sobie tabela z forum, ktorej struktura przedstawia sie nastepujaco:

forum_id
forum_parent
forum_subject
left_id
right_id

forum_parent przechowuje ID galezi - rodzica. Czyli mamy np. taka strukture forum:

Kategoria 1
   Forum 1
      Forum 2
Kategoria 2

W tabeli takie dane prezentuja sie nastepujaco:

forum_id  | forum_parent | forum_subject | left_id | right_id
---------------------------------------------------------------------
1             | 0                   | Kategoria 1     | 1        | 6
----------------------------------------------------------------------
2             | 1                   | Forum 1          | 2        | 5            
----------------------------------------------------------------------
3             | 2                   | Forum 2          | 3        | 4
----------------------------------------------------------------------
4             | 0                   | Kategoria 2     | 7        | 8

Teraz chodzi mi o to, aby przeniesc galaz Forum 1 wraz z galeziami - potomkami. Czyli, zeby to wygladalo tak:

Kategoria 1
Kategoria 2
  Forum 1
    Forum 2

Procedura dodawania:

CREATE DEFINER=`root`@`localhost` FUNCTION `FORUM_ADD`(forumParentId SMALLINT) RETURNS smallint(6)
BEGIN
        DECLARE leftId SMALLINT DEFAULT 0;
        DECLARE rightId SMALLINT DEFAULT 1;
        DECLARE forumOrder SMALLINT DEFAULT 0;

        IF NOT forumParentId THEN
                SELECT MAX(right_id) + 1 AS right_id INTO rightId FROM coyote_forum;

                IF rightId IS NULL THEN
                        SET rightId = 1;
                END IF;
        ELSE

                SELECT left_id, right_id INTO leftId, rightId FROM coyote_forum WHERE forum_id = forumParentId;

                UPDATE coyote_forum SET right_id = right_id + 2 WHERE right_id >= rightId;
                UPDATE coyote_forum SET left_id = left_id + 2 WHERE left_id > rightId;
        END IF;

        SET leftId = rightId;
        SET rightId = rightId + 1;

        SELECT MAX(forum_order) AS forum_order INTO forumOrder FROM coyote_forum WHERE forum_parent = forumParentId;
        IF forumOrder IS NULL THEN
                SET forumOrder = 0;
        END IF;
        SET forumOrder = forumOrder + 1;

        INSERT INTO coyote_forum(forum_parent, left_id, right_id, forum_order) VALUES(forumParentId, leftId, rightId, forumOrder);
        RETURN LAST_INSERT_ID();
END

Procedura usuwania:

CREATE DEFINER=`root`@`localhost` PROCEDURE `FORUM_DELETE`(forumId SMALLINT)
BEGIN
        DECLARE leftId SMALLINT DEFAULT 0;
        DECLARE rightId SMALLINT DEFAULT 0;

        SELECT left_id, right_id INTO leftId, rightId FROM coyote_forum WHERE forum_id = forumId;
        IF leftId > 0 and rightId > 0 THEN

                UPDATE coyote_forum SET right_id = right_id - 2 WHERE left_id < rightId AND right_id > rightId;
                UPDATE coyote_forum SET left_id = left_id - 2, right_id = right_id - 2 WHERE left_id > rightId;

                CALL FORUM_ORDER(forumId);
                DELETE FROM coyote_forum WHERE forum_id = forumId;
        END IF;
END

Ale kurde nie moge sobie poradzic z przenoszeniem galezi wraz z potomkami :/ Gdzies mam luki w algorytmie. Zaznaczam, ze usuwanie i wstawianie od nowa nie wchodzi w gre! forum_id musi zostac zachowane!

Mam procedure, ktora radzi sobie z przenoszeniem, ale jedynie pojedynczych galezi - bez potomkow:

CREATE DEFINER=`root`@`localhost` PROCEDURE `FORUM_MOVE`(forumId SMALLINT, forumParentId SMALLINT)
BEGIN
        DECLARE leftId SMALLINT DEFAULT 0;
        DECLARE rightId SMALLINT DEFAULT 0;
        DECLARE parentId SMALLINT DEFAULT 0;
        DECLARE forumOrder SMALLINT DEFAULT 0;

        SELECT forum_parent, left_id, right_id INTO parentId, leftId, rightId FROM coyote_forum WHERE forum_id = forumId;
        IF leftId > 0 and rightId > 0 THEN

                UPDATE coyote_forum SET right_id = right_id - 2 WHERE left_id < rightId AND right_id > rightId;
                UPDATE coyote_forum SET left_id = left_id - 2, right_id = right_id - 2 WHERE left_id > rightId;

                IF NOT forumParentId THEN
                        SELECT MAX(right_id) + 1 AS right_id INTO rightId FROM coyote_forum;
                ELSE

                        SELECT left_id, right_id INTO leftId, rightId FROM coyote_forum WHERE forum_id = forumParentId;

                        UPDATE coyote_forum SET right_id = right_id + 2 WHERE right_id >= rightId;
                        UPDATE coyote_forum SET left_id = left_id + 2 WHERE left_id > rightId;

                END IF;

                SET leftId = rightId;
                SET rightId = rightId + 1;

                CALL FORUM_ORDER(forumId);
                SELECT MAX(forum_order) + 1 INTO forumOrder FROM coyote_forum WHERE forum_parent = forumParentId;
                IF forumOrder IS NULL THEN
                        SET forumOrder = 1;
                END IF;      

                UPDATE coyote_forum SET forum_parent = forumParentId, left_id = leftId, right_id = rightId, forum_order = forumOrder WHERE forum_id = forumId;
        END IF;
END

Czy ktos ma moze pomysl na algorytm umozliwiajacy przenoszenie wraz z potomkami?