Перестраиваем Nested Sets в PrestaShop SQL запросом

test
Добрый человек описал алгоритм и функцию перестройки левого и правого индексов для Nested Sets.
Статья на хабре
Код на SQL Fiddle

Происходит восстановление индексов для значения по id_parent

Для PrestaShop этот код выглядит так:
-- По умолчанию у индексов значение 0, сменим на NULL
alter table pref_category modify nleft int unsigned default null;
alter table pref_category modify nright int unsigned default null;

DELIMITER //

-- Создаём ту самую функцию
DROP FUNCTION IF EXISTS rebuild_nested_set_tree//
CREATE FUNCTION rebuild_nested_set_tree()
RETURNS INT DETERMINISTIC MODIFIES SQL DATA
BEGIN
-- Изначально сбрасываем все границы в NULL
UPDATE pref_category t SET nleft = NULL, nright = NULL;

-- Устанавливаем границы корневым элементам
SET @i := 0;
UPDATE pref_category t SET nleft = (@i := @i + 1), nright = (@i := @i + 1)
WHERE t.id_parent = 0;

forever: LOOP
-- Находим элемент с минимальной правой границей -- самый левый в дереве
SET @id_parent := NULL;
SELECT t.id_category, t.nright FROM pref_category t, pref_category tc
WHERE t.id_category = tc.id_parent AND tc.nleft IS NULL AND t.nright IS NOT NULL
ORDER BY t.nright LIMIT 1 INTO @id_parent, @parent_right;

-- Выходим из бесконечности, когда у нас уже нет незаполненных элементов
IF @id_parent IS NULL THEN LEAVE forever; END IF;

-- Сохраняем левую границу текущего ряда
SET @current_left := @parent_right;

-- Вычисляем максимальную правую границу текущего ряда
SELECT @current_left + COUNT(*) * 2 FROM pref_category
WHERE id_parent = @id_parent INTO @parent_right;

-- Вычисляем длину текущего ряда
SET @current_length := @parent_right - @current_left;

-- Обновляем правые границы всех элементов, которые правее
UPDATE pref_category t SET nright = nright + @current_length
WHERE nright >= @current_left ORDER BY nright;

-- Обновляем левые границы всех элементов, которые правее
UPDATE pref_category t SET nleft = nleft + @current_length
WHERE nleft > @current_left ORDER BY nleft;

-- И только сейчас обновляем границы текущего ряда
SET @i := (@current_left - 1);
UPDATE pref_category t SET nleft = (@i := @i + 1), nright = (@i := @i + 1)
WHERE id_parent = @id_parent ORDER BY id_category;
END LOOP;

-- Возвращаем самый самую правую границу для дальнейшего использования
RETURN (SELECT MAX(nright) FROM pref_category t);
END//

DELIMITER ;


Запускаем переиндексацию:
SELECT rebuild_nested_set_tree();


Вот и все, дерево переиндексировано. Вернем на место значения по умолчанию для индексов, так как с null индексы не работают, их и не должно быть:
alter table pref_category modify nleft int unsigned default 0;
alter table pref_category modify nright int unsigned default 0;
Категория: 
Share/Save

Делитесь с друзьями в социальных сетях! Оставляйте комментарии!

Share/Save

Это Вам так же может быть интересно!