RelationalDesign: V1__init_ddl.sql

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