Пусть есть таблицы:
Код: Выделить всё
CREATE TABLE Projects (
Project_ID BIGINT NOT NULL,
Parent_ID BIGINT,
Level SMALLINT,
CONSTRAINT PK_Projects PRIMARY KEY (Project_ID)
);
CREATE TABLE Project_Users (
Project_PF BIGINT NOT NULL,
User_PF BIGINT NOT NULL,
Level SMALLINT,
Role SMALLINT,
CONSTRAINT PK_Project_Users PRIMARY KEY (Project_PF, User_PF)
);
Код: Выделить всё
CREATE PROCEDURE TREE_PROJECTS_GET_NODES_ID (
ANID BIGINT,
SELF SMALLINT)
RETURNS (
ID BIGINT)
AS
BEGIN
IF ( (:SELF > 0) AND EXISTS(SELECT PROJECT_ID FROM PROJECTS WHERE PROJECT_ID = :ANID) ) THEN
BEGIN
ID = :ANID;
SUSPEND;
END
FOR SELECT PROJECT_ID FROM PROJECTS
WHERE PARENT_ID = :ANID INTO :ID
DO FOR SELECT ID FROM TREE_PROJECTS_GET_NODES_ID(:ID, 1) INTO :ID
DO SUSPEND;
END^
Пусть есть дерево:
Код: Выделить всё
1
|-2-
|-3
|-4
На мой взгляд, есть два способа дать права пользователю на определенное поддерево. В нашем случае, таблица Project_Users будет выглядеть:
1 способ.
project_pf=1, user_pf=1, level=0, role=100
project_pf=3, user_pf=2, level=2, role=10
Т.е. давать права на поддерево.
2 способ.
project_pf=1, user_pf=1, level=0, role=100
project_pf=2, user_pf=1, level=0, role=100
project_pf=3, user_pf=1, level=0, role=100
project_pf=4, user_pf=1, level=0, role=100
project_pf=3, user_pf=2, level=2, role=10
project_pf=4, user_pf=2, level=2, role=10
Т.е. давать права на каждый объект.
Здесь Level - это уровень в дереве ( корень - 0 уровень, узлы поддерева корня - 1 и т.д.) на котором пользователь получил права. Т.е. первый пользователь получил права на 0 уровне, а второй - на втором уровне.
Теперь по селектам.
В первом случае, что бы вытащить права придется писать
Код: Выделить всё
LEFT JOIN
PROJECT_USERS PS ON PS.PROJECT_PF IN (
SELECT ID FROM TREE_PROJECTS_GET_NODES_ID(8, 1)
) ...
Можно, конечно, предварительно вычислить SELECT ID FROM TREE_PROJECTS_GET_NODES_ID(8, 1). Т.е. привести к виду
Код: Выделить всё
LEFT JOIN
PROJECT_USERS PS ON PS.PROJECT_PF IN (
1,2,3,4,5,6
) ...
Во втором случае.
Код: Выделить всё
LEFT JOIN
PROJECT_USERS PS ON PS.PROJECT_PF = PROJECT_FK
) ...
Но появляется избыточность в таблице PROJECT_USERS, надо писать дополнительные триггеры, например, если добавился проект (таблица PROJECTS):
Код: Выделить всё
INSERT INTO PROJECT_USERS (PROJECT_PF, USER_PF, LEVEL, ROLE)
SELECT NEW.PROJECT_ID, USER_PF, ROLE, LEVEL FROM PROJECT_USERS WHERE PROJECT_PF = NEW.PARENT_ID;
Еще если мне надо дополнительное поле в таблице PROJECT_USERS то оно так и будет дублироваться на все поддеревья. В этом и избыточность.
Как правильно дать права на элементы дерева?