RelationalDesign: V1__init_ddl.2.sql

File V1__init_ddl.2.sql, 15.0 KB (added by 226026, 13 days ago)
Line 
1--- Trigger before update/insert za check na iminjata topic/discussion -> OK
2--- Trigger za ko ke adnit dete na topic thread sho e vo proekt, da go dodajt kako belongs_to vo proektot
3--- Trigger za check dali reply na discussion thread pripagjat na ist topic thread kako na toj so mu pret reply
4--- IMENUVANJE: triggeri so provervat nesto prefix = check, funkcii za istite prefix = validate
5--- Nemame contraint sho velit deka sekoj topic thread trebat da e moderiran
6DROP TABLE IF EXISTS users CASCADE;
7DROP TABLE IF EXISTS moderator CASCADE;
8DROP TABLE IF EXISTS developer CASCADE;
9DROP TABLE IF EXISTS project_manager CASCADE;
10DROP TABLE IF EXISTS thread CASCADE;
11DROP TABLE IF EXISTS likes CASCADE;
12DROP TABLE IF EXISTS topic_threads_moderators CASCADE;
13DROP TABLE IF EXISTS tag CASCADE;
14DROP TABLE IF EXISTS tag_threads CASCADE;
15DROP TABLE IF EXISTS topic_thread CASCADE;
16DROP TABLE IF EXISTS topic_belongs_to_project CASCADE;
17DROP TABLE IF EXISTS blacklisted_user CASCADE;
18DROP TABLE IF EXISTS project_thread CASCADE;
19DROP TABLE IF EXISTS discussion_thread CASCADE;
20DROP TABLE IF EXISTS developer_associated_with_project CASCADE;
21DROP TABLE IF EXISTS permissions CASCADE;
22DROP TABLE IF EXISTS project_roles CASCADE;
23DROP TABLE IF EXISTS users_project_roles CASCADE;
24DROP TABLE IF EXISTS project_roles_permissions CASCADE;
25DROP TABLE IF EXISTS project_request CASCADE;
26DROP TABLE IF EXISTS report CASCADE;
27DROP TABLE IF EXISTS channel CASCADE;
28DROP TABLE IF EXISTS messages CASCADE;
29DROP TABLE IF EXISTS threads_moderators CASCADE;
30DROP TYPE IF EXISTS status;
31DROP VIEW IF EXISTS v_topic_thread CASCADE;
32DROP VIEW IF EXISTS v_project_thread CASCADE;
33DROP VIEW IF EXISTS v_discussion_thread CASCADE;
34DROP VIEW IF EXISTS v_project_owner CASCADE;
35DROP VIEW IF EXISTS v_moderator CASCADE;
36drop function if exists fn_insert_project_manager CASCADE;
37drop function if exists fn_insert_topics_creator_as_moderator CASCADE;
38drop function if exists fn_validate_topic_title CASCADE;
39drop function if exists clean_tables CASCADE;
40drop function if exists clean_routines CASCADE;
41DROP TRIGGER IF EXISTS validate_same_parent ON discussion_thread CASCADE;
42drop table if exists topic_guidelines cascade;
43drop table if exists submission cascade;
44drop table if exists feedback;
45
46
47---- DDL
48CREATE TABLE users
49(
50 id SERIAL PRIMARY KEY,
51 username VARCHAR(32) UNIQUE NOT NULL,
52 email varchar(60) not null,
53 name varchar(32) not null,
54 is_activate bool DEFAULT true,
55 password VARCHAR(72),
56 description VARCHAR(200),
57 registered_at TIMESTAMP DEFAULT NOW(),
58 sex VARCHAR(1)
59);
60CREATE TABLE moderator
61(
62 id INT PRIMARY KEY REFERENCES users (id) on delete cascade
63);
64CREATE TABLE developer
65(
66 id INT PRIMARY KEY REFERENCES users (id) on delete cascade
67);
68CREATE TABLE project_manager
69(
70 id INT PRIMARY KEY REFERENCES users (id) on delete cascade
71);
72CREATE TABLE thread
73(
74 id SERIAL PRIMARY KEY,
75 content TEXT,
76 created_at timestamp DEFAULT NOW(),
77 user_id INT REFERENCES users (id) NOT NULL --IS_CREATED_BY TOTAL
78);
79CREATE TABLE topic_thread
80(
81 title VARCHAR(256) NOT NULL,
82 id INT PRIMARY KEY REFERENCES thread(id) on delete cascade, --INHERITANCE
83 parent_id int REFERENCES thread(id) on delete CASCADE --PARENT
84);
85create table topic_guidelines
86(
87 id serial,
88 topic_id int references topic_thread(id) on delete cascade,
89 description text,
90 PRIMARY KEY (id, topic_id)
91);
92CREATE TABLE discussion_thread
93(
94 id INT PRIMARY KEY REFERENCES thread(id) on delete cascade, --INHERITANCE,
95 parent_id int REFERENCES thread(id) on delete CASCADE NOT NULL --PARENT TOTAL BIGINT
96);
97CREATE TABLE project_thread
98(
99 title VARCHAR(256) UNIQUE NOT NULL,
100 repo_url TEXT,
101 id INT PRIMARY KEY REFERENCES thread (id) on delete cascade --INHERITANCE
102);
103CREATE TABLE likes
104(
105 user_id INT REFERENCES users (id) on delete cascade ,
106 thread_id INT REFERENCES thread (id) on delete cascade,
107 PRIMARY KEY (user_id, thread_id)
108);
109CREATE TABLE topic_threads_moderators
110(
111 thread_id INT REFERENCES topic_thread(id) ON DELETE CASCADE,
112 user_id INT REFERENCES moderator(id) ON DELETE CASCADE,
113 started_at TIMESTAMP DEFAULT NOW(),
114 PRIMARY KEY (thread_id, user_id)
115);
116CREATE TABLE tag
117(
118 name VARCHAR(64) PRIMARY KEY,
119 creator_id int REFERENCES moderator(id) on delete CASCADE not null
120);
121CREATE TABLE tag_threads
122(
123 thread_id INT REFERENCES thread (id) ON DELETE CASCADE,
124 tag_name VARCHAR(64) REFERENCES tag (name) ON DELETE CASCADE,
125 PRIMARY KEY (thread_id, tag_name)
126);
127
128CREATE TABLE blacklisted_user
129(
130 topic_id INT REFERENCES topic_thread(id) ON DELETE CASCADE, --BLACLISTED_FROM
131 user_id INT REFERENCES users(id) ON DELETE CASCADE, --REFERS_TO
132 moderator_id INT REFERENCES moderator(id) ON DELETE CASCADE, --BLACKLISTED_BY
133 start_date TIMESTAMP,
134 end_date TIMESTAMP,
135 reason TEXT,
136 PRIMARY KEY (user_id, moderator_id, topic_id, start_date)
137);
138
139CREATE TABLE developer_associated_with_project
140(
141 project_id INT REFERENCES project_thread(id) on delete cascade,
142 developer_id INT REFERENCES developer(id) on delete cascade,
143 started_at TIMESTAMP DEFAULT NOW(),
144 ended_at TIMESTAMP,
145 PRIMARY KEY (project_id, developer_id, started_at)
146);
147---DO TUKA
148CREATE TABLE permissions
149(
150 name VARCHAR(32) PRIMARY KEY
151);
152CREATE TABLE project_roles
153(
154 name VARCHAR(32),
155 project_id INT REFERENCES project_thread(id) ON DELETE CASCADE NOT NULL, --VALID_IN
156 description TEXT,
157 PRIMARY KEY (name, project_id)
158);
159CREATE TABLE users_project_roles
160(
161 user_id INT REFERENCES developer(id) on delete cascade,
162 project_id INT,
163 role_name VARCHAR(32),
164 FOREIGN KEY (role_name, project_id)
165 REFERENCES project_roles (name, project_id) ON DELETE CASCADE,
166 PRIMARY KEY (user_id, project_id, role_name)
167);
168CREATE TABLE project_roles_permissions
169(
170 permission_name VARCHAR(32) REFERENCES permissions (name),
171 role_name VARCHAR(32),
172 project_id INT,
173 FOREIGN KEY (role_name, project_id)
174 REFERENCES project_roles (name, project_id) ON DELETE CASCADE,
175 PRIMARY KEY (permission_name, role_name, project_id)
176);
177
178create table submission(
179 id serial primary key,
180 created_at TIMESTAMP default now() not null,
181 description VARCHAR(200) NOT NULL,
182 status varchar(32) default 'PENDING' CHECK(status IN ( 'ACCEPTED', 'DENIED', 'PENDING')),
183 created_by int REFERENCES users(id) not null
184);
185
186CREATE TABLE project_request
187(
188 id int PRIMARY KEY REFERENCES submission(id),
189 project_id INT REFERENCES thread (id) ON DELETE CASCADE NOT NULL --RECIEVES
190);
191
192create table feedback (
193 description TEXT,
194 submission_type varchar(1) CHECK(submission_type IN ('P','R')),
195 created_at timestamp default now() not null,
196 created_by int references users(id) NOT NULL, --WRITTEN_BY
197 submission_id int PRIMARY KEY references submission(id) on delete cascade
198);
199
200CREATE TABLE report
201(
202 id int PRIMARY KEY REFERENCES submission(id),
203 thread_id INT REFERENCES topic_thread(id) on delete cascade not null, --FOR_MISCONDUCT
204 for_user_id INT REFERENCES users (id) on delete cascade not null --ABOUT
205);
206CREATE TABLE channel
207(
208 name VARCHAR(64),
209 description VARCHAR(200),
210 project_id INT REFERENCES project_thread(id) ON DELETE CASCADE NOT NULL, --HAS
211 developer_id INT REFERENCES developer(id) NOT NULL, --CONSTRUCTS
212 PRIMARY KEY (name, project_id)
213);
214CREATE TABLE messages
215(
216 sent_at TIMESTAMP,
217 content VARCHAR(200) NOT NULL,
218 sent_by INT REFERENCES developer(id),
219 project_id INT,
220 channel_name VARCHAR(64),
221 FOREIGN KEY (channel_name, project_id)
222 REFERENCES channel (name, project_id) ON DELETE CASCADE,
223 PRIMARY KEY (channel_name, project_id, sent_at, sent_by)
224);
225
226
227------------------------VIEWS-----------------------------
228CREATE OR REPLACE VIEW v_project_thread
229AS
230SELECT thread.id, content, user_id, title, repo_url
231FROM project_thread project
232 JOIN thread
233 ON project.id = thread.id;
234CREATE OR REPLACE VIEW v_topic_thread
235AS
236SELECT thread.id, content, user_id, title, parent_id
237FROM topic_thread topic
238 JOIN thread
239 ON topic.id = thread.id;
240CREATE OR REPLACE VIEW v_moderator
241AS
242SELECT users.id, username, is_activate, password, description, registered_at, sex
243FROM moderator
244 JOIN users ON moderator.id = users.id;
245
246create or replace view v_discussion_thread
247as
248with recursive
249 depth_table as
250 (select parent_id, id, 0 as depth
251 from discussion_thread
252 UNION ALL
253 select discuss.parent_id, dpth.id, dpth.depth + 1
254 from depth_table dpth
255 join discussion_thread discuss
256 on dpth.parent_id = discuss.id),
257 tmp as (select id, max(depth) as depth
258 from depth_table
259 group by id)
260select d.id as id, t.user_id as user_id, d.depth as depth, d1.parent_id as parent_id, t.created_at as "created_at"
261from tmp d
262 join depth_table d1
263 on d.id = d1.id and d1.depth = d.depth
264 join thread t
265 on t.id = d.id;
266-------------------------- FUNCTIONS ----------------------
267CREATE OR REPLACE FUNCTION fn_validate_topic_title()
268 RETURNS TRIGGER
269 LANGUAGE plpgsql
270AS
271$$
272BEGIN
273 IF new.title IN
274 (SELECT title
275 FROM topic_thread
276 AS t
277 WHERE t.parent_id = new.parent_id
278 OR (t.parent_id IS NULL AND new.parent_id IS NULL)
279 )
280 THEN
281 RAISE EXCEPTION 'There already exists a topic with title % in parent topic with id %',new.title,new.parent_id;
282 END IF;
283 RETURN new;
284END;
285$$;
286create or replace function check_if_user_exists_in(table_name text, field_name text, field_value text) returns boolean
287 language plpgsql
288as
289$$
290DECLARE
291 result BOOL;
292BEGIN
293 EXECUTE format('SELECT EXISTS (SELECT 1 FROM %I WHERE %I = %L)', table_name, field_name, field_value)
294 INTO result;
295 RETURN result;
296END
297$$;
298CREATE OR REPLACE FUNCTION fn_insert_topics_creator_as_moderator()
299 RETURNS TRIGGER
300 LANGUAGE plpgsql
301AS
302$$
303DECLARE
304 v_user_id INT;
305BEGIN
306 SELECT v_topic_thread.user_id
307 INTO v_user_id
308 FROM v_topic_thread
309 WHERE v_topic_thread.id = new.id;
310 IF not check_if_user_exists_in('moderator', 'id', v_user_id::text) THEN
311 INSERT INTO moderator values (v_user_id);
312 END IF;
313 INSERT INTO topic_threads_moderators(thread_id, user_id) VALUES (new.id, v_user_id);
314 RETURN NEW;
315END
316$$;
317
318CREATE OR REPLACE FUNCTION fn_insert_project_manager()
319 RETURNS TRIGGER
320 LANGUAGE plpgsql
321AS
322$$
323DECLARE
324 usrId INT;
325 new_project_id INT;
326BEGIN
327 SELECT user_id, id
328 into usrId,new_project_id
329 FROM v_project_thread p
330 WHERE NEW.id = p.id;
331 IF not check_if_user_exists_in('developer_associated_with_project', 'developer_id', usrId::text) THEN
332 INSERT INTO developer_associated_with_project(project_id, developer_id, started_at)
333 values (new_project_id, usrId, NOW());
334 end if;
335 IF not check_if_user_exists_in('project_manager', 'id', usrId::text) THEN
336 INSERT INTO project_manager VALUES (usrId);
337 end if;
338 RETURN NEW;
339END
340$$;
341create or replace function fn_remove_unused_tags()
342 returns trigger
343 language plpgsql
344as
345$$
346BEGIN
347 IF not check_if_user_exists_in('tag_threads', 'tag_name', old.tag_name)
348 THEN
349 delete from tag t where t.name = old.tag_name;
350 end if;
351 return old;
352end;
353$$;
354create or replace function fn_add_dev_if_not_exist()
355returns trigger
356language plpgsql
357as $$
358 BEGIN
359 IF NOT check_if_user_exists_in('developer','id',new.developer_id::text) THEN
360 INSERT INTO developer values (NEW.developer_id);
361 end if;
362 RETURN new;
363 end;
364 $$;
365
366create or replace function fn_insert_general_for_project()
367 returns trigger
368 language plpgsql
369as $$
370DECLARE
371 developer_id INT;
372BEGIN
373 select user_id
374 into developer_id
375 from thread t
376 where t.id=NEW.id;
377
378 insert into channel(name,description,project_id,developer_id)
379 values ('General','General',NEW.id,developer_id);
380
381 return new;
382end;
383$$;
384
385CREATE OR REPLACE FUNCTION fn_defined_by_total_custom_roles()
386 RETURNS trigger
387 LANGUAGE plpgsql
388AS $$
389BEGIN
390IF not exists(
391 select 1
392 from project_roles_permissions p
393 where p.role_name=OLD.role_name and p.project_id = OLD.project_id
394) THEN
395 DELETE FROM project_roles
396 where name=OLD.role_name and project_id=OLD.project_id;
397END IF;
398RETURN OLD;
399END;
400$$
401;
402
403CREATE OR REPLACE FUNCTION fn_remove_orphan_moderator()
404 RETURNS trigger
405 LANGUAGE plpgsql
406AS $function$
407BEGIN
408 IF not exists (
409 select 1
410 from topic_threads_moderators t
411 where t.user_id = OLD.user_id
412 )
413THEN
414 DELETE FROM moderator where id=OLD.user_id;
415 END IF;
416 IF not exists (
417 select 1
418 from topic_threads_moderators t
419 where t.thread_id = OLD.thread_id
420 )
421THEN
422 DELETE FROM topic_thread where id = OLD.thread_id;
423 delete from thread where id = OLD.thread_id;
424 END IF;
425 RETURN OLD;
426END;
427$function$
428;
429
430-- create or replace function fn_remove_thread()
431-- returns trigger
432-- language plpgsql
433-- as
434-- $$
435-- BEGIN
436-- delete from thread where id = OLD.id;
437-- return OLD;
438-- END;
439-- $$;
440
441
442-------------------------- TRIGGERS ----------------------
443
444CREATE OR REPLACE TRIGGER tr_check_topic_name --RADI
445 BEFORE INSERT OR UPDATE
446 ON topic_thread
447 FOR EACH ROW
448EXECUTE FUNCTION fn_validate_topic_title();
449CREATE OR REPLACE TRIGGER tr_insert_topics_creator_as_moderator --RADI
450 AFTER INSERT
451 ON topic_thread
452 FOR EACH ROW
453EXECUTE FUNCTION fn_insert_topics_creator_as_moderator();
454----
455create or replace TRIGGER tr_defined_by_total_custom_roles
456after delete
457on project_roles_permissions
458for each row
459execute function fn_defined_by_total_custom_roles();
460
461CREATE OR REPLACE TRIGGER tr_remove_orphan_moderator --RADI
462AFTER DELETE
463ON topic_threads_moderators
464FOR EACH ROW
465EXECUTE FUNCTION fn_remove_orphan_moderator();
466
467
468CREATE OR REPLACE TRIGGER tr_a_insert_project_manager --RADI
469 AFTER INSERT
470 ON project_thread
471 FOR EACH ROW
472EXECUTE FUNCTION fn_insert_project_manager();
473
474create or replace trigger tr_remove_unused_tags --RADI
475 after delete
476 on tag_threads
477 for each row
478execute function fn_remove_unused_tags();
479
480create or replace trigger tr_add_dev_if_not_exist --RADI
481before insert on developer_associated_with_project
482 for each row
483 execute function fn_add_dev_if_not_exist();
484
485create or replace trigger tr_insert_general_for_project --RADI
486 after insert on project_thread
487 for each row
488execute function fn_insert_general_for_project();
489
490-- create or replace trigger tr_remove_thread_from_project
491-- after delete
492-- on project_thread
493-- for each row
494-- execute function fn_remove_thread();
495--
496-- create or replace trigger tr_remove_thread_from_topic
497-- after delete
498-- on topic_thread
499-- for each row
500-- execute function fn_remove_thread();
501--
502-- create or replace trigger tr_remove_thread_from_discussion
503-- after delete
504-- on discussion_thread
505-- for each row
506-- execute function fn_remove_thread();