DELIMITER $$ CREATE OR REPLACE DEFINER=`root`@`localhost` PROCEDURE `vn2008`.`nest_move`( vTable VARCHAR(45) ,idNODE INT ,idFATHER INT ) BEGIN DECLARE myRight INT; DECLARE myLeft INT; DECLARE myWidth INT; DECLARE fatherRight INT; DECLARE fatherLeft INT; DECLARE gap INT; SET vTable = util.quoteIdentifier(vTable); DROP TEMPORARY TABLE IF EXISTS aux; CREATE TEMPORARY TABLE aux SELECT 0 as rgt, 0 as lft, 0 as wdt, 0 as frg, 0 as flf; -- Averiguamos el ancho de la rama EXECUTE IMMEDIATE CONCAT( 'UPDATE aux a JOIN ', vTable, ' t SET a.wdt = t.rgt - t.lft + 1 WHERE t.id = ?') USING idNODE; -- Averiguamos la posicion del nuevo padre EXECUTE IMMEDIATE CONCAT( 'UPDATE aux a JOIN ', vTable, ' t SET a.frg = t.rgt, a.flf = t.lft WHERE t.id = ?') USING idFATHER; SELECT wdt, frg, flf INTO myWidth, fatherRight, fatherLeft FROM aux; -- 1º Incrementamos los valores de todos los nodos a la derecha del punto de inserción (fatherRight) , para hacer sitio EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET rgt = rgt + ? WHERE rgt >= ? ORDER BY rgt DESC') USING myWidth, fatherRight; EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET lft = lft + ? WHERE lft >= ? ORDER BY lft DESC') USING myWidth, fatherRight; -- Es preciso recalcular los valores del nodo en el caso de que estuviera a la derecha del nuevo padre EXECUTE IMMEDIATE CONCAT( 'UPDATE aux a JOIN ', vTable, ' t SET a.rgt = t.rgt, a.lft = t.lft WHERE t.id = ?') USING idNODE; SELECT lft, rgt, frg - lft INTO myLeft, myRight, gap FROM aux; -- 2º Incrementamos el valor de todos los nodos a trasladar hasta alcanzar su nueva posicion EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET lft = lft + ? WHERE lft BETWEEN ? AND ? ORDER BY lft DESC') USING gap, myLeft, myRight; EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET rgt = rgt + ? WHERE rgt BETWEEN ? AND ? ORDER BY rgt DESC') USING gap, myLeft, myRight; -- 3º Restaremos a todos los nodos resultantes, a la derecha de la posicion arrancada el ancho de la rama escindida EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET lft = lft - ? WHERE lft > ? ORDER BY lft') USING myWidth, myLeft; EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET rgt = rgt - ? WHERE rgt > ? ORDER BY rgt') USING myWidth, myRight; DROP TEMPORARY TABLE aux; END$$ DELIMITER ;