DELIMITER $$ CREATE OR REPLACE DEFINER=`vn`@`localhost` PROCEDURE `vn`.`balanceNestTree_move`( vSelf INT, vFather INT ) BEGIN /** * Mueve un nodo dentro de la estructura de árbol de vn.balanceNestTree. * * @param vSelf Identificador del nodo * @param vFather Identificador del nuevo padre del nodo */ DECLARE vTable VARCHAR(45) DEFAULT util.quoteIdentifier('balanceNestTree'); DECLARE vRight INT; DECLARE vLeft INT; DECLARE vWidth INT; DECLARE vFatherRight INT; DECLARE vFatherLeft INT; DECLARE vGap INT; CREATE OR REPLACE TEMPORARY TABLE tAux SELECT 0 rgt, 0 lft, 0 wdt, 0 frg, 0 flf; -- Averiguamos el ancho de la rama EXECUTE IMMEDIATE CONCAT( 'UPDATE tAux a JOIN ', vTable, ' t SET a.wdt = t.rgt - t.lft + 1 WHERE t.id = ?') USING vSelf; -- Averiguamos la posicion del nuevo padre EXECUTE IMMEDIATE CONCAT( 'UPDATE tAux a JOIN ', vTable, ' t SET a.frg = t.rgt, a.flf = t.lft WHERE t.id = ?') USING vFather; SELECT wdt, frg, flf INTO vWidth, vFatherRight, vFatherLeft FROM tAux; -- 1º Incrementamos los valores de todos los nodos a la derecha -- del punto de inserción (vFatherRight) , para hacer sitio EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET rgt = rgt + ? WHERE rgt >= ? ORDER BY rgt DESC') USING vWidth, vFatherRight; EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET lft = lft + ? WHERE lft >= ? ORDER BY lft DESC') USING vWidth, vFatherRight; -- Es preciso recalcular los valores del nodo en el -- caso de que estuviera a la derecha del nuevo padre EXECUTE IMMEDIATE CONCAT( 'UPDATE tAux a JOIN ', vTable, ' t SET a.rgt = t.rgt, a.lft = t.lft WHERE t.id = ?') USING vSelf; SELECT lft, rgt, frg - lft INTO vLeft, vRight, vGap FROM tAux; -- 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 vGap, vLeft, vRight; EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET rgt = rgt + ? WHERE rgt BETWEEN ? AND ? ORDER BY rgt DESC') USING vGap, vLeft, vRight; -- 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 vWidth, vLeft; EXECUTE IMMEDIATE CONCAT( 'UPDATE ', vTable, 'SET rgt = rgt - ? WHERE rgt > ? ORDER BY rgt') USING vWidth, vRight; DROP TEMPORARY TABLE tAux; END$$ DELIMITER ;