Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Курсовая работа. БД

.pdf
Скачиваний:
2
Добавлен:
07.01.2025
Размер:
7.39 Mб
Скачать

21

Рисунок 16 - Результат назначения прав

Так как директору допустим лишь просмотр всех таблиц, для назначение ему таких полномочий можно использовать:

GRANT SELECT ON ALL TABLES IN SCHEMA public TO director;

Рисунок 17 - Результат назначения прав

Назначение прав для модератора представлено ниже:

GRANT SELECT ON friends TO moderator;

GRANT SELECT ON communities TO moderator;

GRANT SELECT, INSERT, UPDATE, DELETE ON users TO moderator;

22

Рисунок 18 - Результат назначения прав

Назначение прав для поддержки пользователей представлено ниже:

GRANT SELECT ON users TO tech_support;

Рисунок 19 - Результат назначения прав

23

Проектирование пользовательского интерфейса

Первое, на что следует обратить внимание - это группы друзей пользователя. В них можно занести лишь тех пользователей, с которыми у пользователя взаимная дружба. Для добавления пользователя в группу, можно завести функцию вида:

CREATE OR REPLACE FUNCTION adding_friend_to_group(gr_id integer, fr_id

integer, us_id integer) RETURNS BOOLEAN AS

$$

begin

if (not exists (select owner_id from groups g where g.owner_id

= us_id and g.id = gr_id)) THEN

raise exception 'Группа с идентификатором --> % не принадлежит пользователю --> %', gr_id, us_id;

end if;

if ((select count(user_id) from friends where user_id = us_id and friend_id = fr_id or user_id = fr_id and friend_id = us_id) != 2) then raise exception 'У пользователей --> % и % дружба не

взаимна', us_id, fr_id;

end if;

insert into friend_group (group_id, friend_id) values (gr_id,

fr_id);

return true;

end;

$$ LANGUAGE plpgsql;

24

Рисунок 20 - Результат создания функции

Рисунок 21 - Результат добавления пользователя в группу друзей

Рисунок 22 - Попытка добавить друга в группу, которая не принадлежит пользователю

25

Рисунок 23 - Попытка добавить пользователя в группу, дружба с которым не взаимна

Стандартные средства реляционной БД не позволяют поддерживать целостность в части групп. То есть, например, возможно ситуация, когда пользователь добавит друга в группу. Но, в какой-то момент, дружба может стать невзаимной в случае, если одна из сторон удалит запись из таблицы friends. В таком случае пользователя также не должно быть в группе друзей. Для этого потребуется реализовать триггер.

Функция, которая будет использоваться в триггере:

CREATE OR REPLACE FUNCTION delete_from_friend_group() RETURNS TRIGGER AS

$$

begin

delete from friend_group where friend_id = old.friend_id and group_id IN (select id from groups where owner_id = old.user_id);

delete from friend_group where friend_id = old.user_id and group_id IN (select id from groups where owner_id = old.friend_id);

RETURN old;

END;

$$ LANGUAGE plpgsql;

Триггер:

CREATE TRIGGER trigger_delete_from_friend_group before delete ON friends

for each row

EXECUTE FUNCTION delete_from_friend_group();

26

Попробуем использовать созданный триггер.

Рисунок 24 - Содержимое таблицы friend_group

Рисунок 25 - Содержимое таблицы friends

27

Попробуем удалить пользователя 3 из друзей пользователя 1, в одностороннем порядке.

Рисунок 26 - Запрос на удаление

Рисунок 27 - Содержимое таблицы friends после удаления

28

Рисунок 28 - Содержимое таблицы friend_group после удаления

Также для сложных запросов можно ввести отдельные функции, чтобы при необходимости - не требовалось вспоминать его синтаксис. Например, запрос на получение распределения друзей по группам определенного пользователя. Скрипт будет иметь вид:

CREATE

OR

REPLACE

FUNCTION

get_count_friend_for_groups(us_id

integer) RETURNS table (title varchar, count_users bigint) AS $$

begin

 

 

 

 

return query select g.title as title, count(fg.group_id) as

count_users from groups g

 

 

 

 

 

left join

friend_group fg on fg.group_id =

g.id

 

 

 

 

 

 

 

where g.owner_id = us_id

 

 

 

group by g.title, fg.group_id;

END;

 

 

 

 

$$ LANGUAGE plpgsql;

 

 

 

Рисунок 29 - Результат вызова созданной функции

29

Для того, чтобы быстрее и удобнее создавать новые группы друзей, введена функция:

CREATE OR REPLACE FUNCTION create_groups_for_user (titles varchar[], user_id integer) RETURNS boolean AS $$

declare

gr_title varchar;

begin

foreach gr_title in array $1 loop

insert into groups (owner_id, title) values (user_id,

gr_title);

end loop; return true;

END;

$$ LANGUAGE plpgsql;

Рисунок 30 - Результат вызова функции

Рисунок 31 - Результат вызова функции

30

Предположим, что при блокировке пользователя - мы должны удалить все связанные с ним записи из таблицы друзей. Для этой цели потребуется ввести триггер. Но, перед его написанием, нужно немного подправить модель данных таблицы users, введя поле active:

alter table users add column active boolean default true; alter table users alter column active set not null;

Рисунок 32 - Результат добавления колонки

Листинг функции, используемой в триггере:

CREATE OR REPLACE FUNCTION delete_friends_on_deactivation_user() RETURNS

TRIGGER AS $$ begin

delete from friends where user_id = old.id or friend_id =

old.id;

RETURN old;

END;

$$ LANGUAGE plpgsql;

Триггер, который будет вызывать перед обновлением записи в таблице users и изменении у нее значения active на false:

CREATE TRIGGER trigger_on_deactivation_user before update ON users

for each row

when (old.active != new.active and new.active = false)

EXECUTE FUNCTION delete_friends_on_deactivation_user();