DELIMITER $$
CREATE OR REPLACE DEFINER=`vn-admin`@`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 ;
