Если вы смотрите на древовидную иерархию, то модель вложенного набора работает довольно хорошо, но включает в себя серьезные изменения в структуре вашей таблицы наследования.
Если вы реализуете произвольный ориентированный граф (например, у вас есть профиль «автор», который может публиковать статьи, но не модерирует комментарии, и профиль «модератор», который может модерировать комментарии, но не публиковать статьи), вы можете хочу искать другое решение.
Одна из возможностей - отказаться от наследования и вручную установить разрешения для каждой группы.
Другая возможность - использовать таблицу наследования для хранения как прямого, так и косвенного наследования (то есть узел будет связан со всеми своими дочерними элементами, использующими «прямые» отношения, а также со всеми его потомками, использующими «косвенные» отношения. ). Эта стратегия требует от вас повторного создания всех косвенных связей в таблице всякий раз, когда вы изменяете одно из прямых отношений (это может быть сделано с помощью простого INSERT SELECT
), но имеет преимущество в том, что требуется только одно соединение для доступа ко всем потомки.
Основная идея:
CREATE TABLE group_inherit (
parent INT NOT NULL,
child INT NOT NULL,
distance INT NOT NULL,
PRIMARY KEY (parent,child)
);
/* Clean up indirect relations */
DELETE FROM group_inherit WHERE distance <> 0;
/* Repeat this for each D > 0 until the maximum distance is reached */
INSERT IGNORE INTO (parent, child, distance)
SELECT fst.parent, snd.child, D
FROM group_inherit fst
INNER JOIN group_inherit snd ON snd.parent = fst.child
WHERE fst.distance = 0 AND snd.distance = D - 1;
/* Select all permissions for a user type */
SELECT perm.*
FROM group_permissions perm
INNER JOIN group_inherit ON perm.moderator = child
WHERE parent = ?
Цикл на расстоянии должен выполняться до тех пор, пока не будет доступно больше элементов расстояния D-1, что можно сделать с помощью запроса выбора или, если у вас есть, метаинформации о том, сколько строк было вставлено.