DatabaseProgramming: console_13.sql

File console_13.sql, 10.4 KB (added by 231166, 5 days ago)
Line 
1--proceduri:
2
3--Kiko:
4--1-Регистрација на нов корисник со почетна претплата
5
6
7CREATE OR REPLACE PROCEDURE sp_register_user(
8 p_first_name VARCHAR,
9 p_last_name VARCHAR,
10 p_username VARCHAR,
11 p_email VARCHAR,
12 p_password VARCHAR,
13 p_subscription_id INT
14)
15LANGUAGE plpgsql AS $$
16DECLARE
17 v_user_id INT;
18BEGIN
19 -- Vmetni nov korisnik
20 INSERT INTO "User" (FirstName, LastName, Username, Email, password, Date_registered)
21 VALUES (p_first_name, p_last_name, p_username, p_email, p_password, CURRENT_DATE)
22 RETURNING UserID INTO v_user_id;
23
24 -- Kreira User_Subscription zapis za noviot korisnik
25 INSERT INTO User_Subscription (UserUserID, SubscriptionSubscriptionID, Start_date, End_date, Status, Auto_renew)
26 VALUES (v_user_id, p_subscription_id, CURRENT_DATE, CURRENT_DATE + INTERVAL '30 days', 'Active', 1);
27
28 RAISE NOTICE 'Korisnikot % % uspeshno registriran so UserID = %', p_first_name, p_last_name, v_user_id;
29
30EXCEPTION
31 WHEN unique_violation THEN
32 RAISE EXCEPTION 'Email % veke postoi vo sistemot.', p_email;
33 WHEN foreign_key_violation THEN
34 RAISE EXCEPTION 'Subscription so ID % ne postoi.', p_subscription_id;
35END;
36$$;
37
38--Зошто би постоела во реален свет:
39--На Netflix/Spotify кога се регистрираш, тоа не е само еден INSERT — треба да се креира корисник, да му се додели план, да се постави почетен датум. Без процедура, фронтендот би морал да праќа 2 одделни барања, со ризик едното да успее а другото да не — процедурата го прави тоа атомски (или се, или ништо).
40
41--2-Додавање содржина во watchlist со проверка за дупликати
42
43CREATE OR REPLACE PROCEDURE sp_add_to_watchlist(
44 p_user_id INT,
45 p_content_id INT
46)
47LANGUAGE plpgsql AS $$
48DECLARE
49 v_exists INT;
50BEGIN
51 -- Proverka dali veke postoi vo watchlist-ot
52 SELECT COUNT(*) INTO v_exists
53 FROM Watchlist
54 WHERE UserUserID = p_user_id AND ContentContentID = p_content_id;
55
56 IF v_exists > 0 THEN
57 RAISE NOTICE 'Sodrzhinata veke e vo watchlist-ot na korisnikot.';
58 RETURN;
59 END IF;
60
61 -- Proverka dali sodrzhinata postoi vo Media
62 IF NOT EXISTS (SELECT 1 FROM Media WHERE ContentID = p_content_id) THEN
63 RAISE EXCEPTION 'Sodrzhinata so ID % ne postoi.', p_content_id;
64 END IF;
65
66 INSERT INTO Watchlist (UserUserID, ContentContentID, dateAdded)
67 VALUES (p_user_id, p_content_id, CURRENT_DATE);
68
69 RAISE NOTICE 'Sodrzhinata % dodadena vo watchlist za korisnik %.', p_content_id, p_user_id;
70
71EXCEPTION
72 WHEN foreign_key_violation THEN
73 RAISE EXCEPTION 'Korisnik % ili sodrzina % ne postoi.', p_user_id, p_content_id;
74END;
75$$;
76
77--Зошто би постоела во реален свет:
78--Кога кликаш "Add to My List" на Netflix, апликацијата не знае дали веќе го имаш додадено — процедурата тоа го решава на ниво на база, без фронтендот да прави extra SELECT прво.
79
80--3- Промена на план на претплата за постоечки корисник
81
82CREATE OR REPLACE PROCEDURE sp_record_watch(
83 p_user_id INT,
84 p_content_id INT,
85 p_watchable_id INT,
86 p_device_id INT,
87 p_progress INT
88)
89LANGUAGE plpgsql AS $$
90BEGIN
91 -- Proverka za progress range
92 IF p_progress < 0 OR p_progress > 100 THEN
93 RAISE EXCEPTION 'Progress mora da bide pomegu 0 i 100.';
94 END IF;
95
96 -- Vmetni vo WatchHistory (trigerot ke go handle 90%+ -> 100%)
97 INSERT INTO WatchHistory (WatchedAt, Progress_percentage, UserUserID, ContentContentID, WatchableWatchableID, DevicesDeviceID)
98 VALUES (CURRENT_DATE, p_progress, p_user_id, p_content_id, p_watchable_id, p_device_id);
99
100 -- Ako e zavrseno gledanjeto i nema reting, isprati NOTICE (vo realna app = notification za rating)
101 IF p_progress >= 90 THEN
102 IF NOT EXISTS (
103 SELECT 1 FROM Rating
104 WHERE UserUserID = p_user_id AND ContentContentID = p_content_id
105 ) THEN
106 RAISE NOTICE 'Korisnik % ja zavrsil sodrzhinata %. Pokanete go da ostavi rejting.', p_user_id, p_content_id;
107 END IF;
108 END IF;
109
110EXCEPTION
111 WHEN foreign_key_violation THEN
112 RAISE EXCEPTION 'Nevaliden user, content, watchable ili device ID.';
113END;
114$$;
115
116--Зошто би постоела во реален свет:
117--Кога корисник на HBO Max upgrade-ува од Basic на Premium, треба да се затвори стариот план и да се отвори нов — а вашиот тригер trigger_log_subscription_status_change автоматски ќе го логира тоа. Процедурата + триgerот работат заедно совршено.
118
119--Damjan:
120
121--1-Снимање на гледање + автоматски рејтинг промпт логика
122CREATE OR REPLACE PROCEDURE sp_record_watch(
123 p_user_id INT,
124 p_content_id INT,
125 p_watchable_id INT,
126 p_device_id INT,
127 p_progress INT
128)
129LANGUAGE plpgsql AS $$
130BEGIN
131 -- Proverka za progress range
132 IF p_progress < 0 OR p_progress > 100 THEN
133 RAISE EXCEPTION 'Progress mora da bide pomegu 0 i 100.';
134 END IF;
135
136 -- Vmetni vo WatchHistory (trigerot ke go handle 90%+ -> 100%)
137 INSERT INTO WatchHistory (WatchedAt, Progress_percentage, UserUserID, ContentContentID, WatchableWatchableID, DevicesDeviceID)
138 VALUES (CURRENT_DATE, p_progress, p_user_id, p_content_id, p_watchable_id, p_device_id);
139
140 -- Ako e zavrseno gledanjeto i nema reting, isprati NOTICE (vo realna app = notification za rating)
141 IF p_progress >= 90 THEN
142 IF NOT EXISTS (
143 SELECT 1 FROM Rating
144 WHERE UserUserID = p_user_id AND ContentContentID = p_content_id
145 ) THEN
146 RAISE NOTICE 'Korisnik % ja zavrsil sodrzhinata %. Pokanete go da ostavi rejting.', p_user_id, p_content_id;
147 END IF;
148 END IF;
149
150EXCEPTION
151 WHEN foreign_key_violation THEN
152 RAISE EXCEPTION 'Nevaliden user, content, watchable ili device ID.';
153END;
154$$;
155
156--Зошто би постоела во реален свет:
157--Секој пат кога паузираш или завршиш нешто на стриминг сервис, апликацијата снима прогрес. Процедурата работи со постоечкиот тригер trigger_auto_complete_progress (90%→100%) и додава логика за рејтинг нотификација — точно kako "How would you rate Stranger Things?" pop-up по завршување.
158
159--2-Поднесување или ажурирање на рејтинг за содржина
160
161CREATE OR REPLACE PROCEDURE sp_submit_rating(
162 p_user_id INT,
163 p_content_id INT,
164 p_rating INT
165)
166LANGUAGE plpgsql AS $$
167DECLARE
168 v_watched INT;
169BEGIN
170 -- Proverka dali korisnikot vosopsto ja gledal sodrzhinata
171 SELECT COUNT(*) INTO v_watched
172 FROM WatchHistory
173 WHERE UserUserID = p_user_id AND ContentContentID = p_content_id;
174
175 IF v_watched = 0 THEN
176 RAISE EXCEPTION 'Korisnikot ne ja gledal sodrzhinata i ne moze da ostavi rejting.';
177 END IF;
178
179 -- Ako veke postoi rejting, UPDATE; inaku INSERT
180 IF EXISTS (SELECT 1 FROM Rating WHERE UserUserID = p_user_id AND ContentContentID = p_content_id) THEN
181 UPDATE Rating
182 SET RatingValue = p_rating, Rating_Date = CURRENT_DATE
183 WHERE UserUserID = p_user_id AND ContentContentID = p_content_id;
184
185 RAISE NOTICE 'Rejtingot azhurirani na % za sodrzina %.', p_rating, p_content_id;
186 ELSE
187 INSERT INTO Rating (Rating_Date, RatingValue, UserUserID, ContentContentID)
188 VALUES (CURRENT_DATE, p_rating, p_user_id, p_content_id);
189
190 RAISE NOTICE 'Nov rejting % vnesen za sodrzina %.', p_rating, p_content_id;
191 END IF;
192
193 -- Trigerot trigger_validate_rating ke go proveri rangot avtomatski
194
195EXCEPTION
196 WHEN check_violation THEN
197 RAISE EXCEPTION 'Rejtingot mora da bide pomegu 1 i 5.';
198END;
199$$;
200
201--Зошто би постоела во реален свет:
202--IMDB/Netflix не дозволуваат рејтинг ако не си гледал — процедурата го enforc-ува тоа. Исто така работи со постоечкиот тригер trigger_validate_rating за валидација на вредноста, и со вашиот индекс idx_rating_content за брзо пребарување.
203
204--3-Деактивирање на корисник — Cancel претплата + чистење на уреди
205CREATE OR REPLACE PROCEDURE sp_deactivate_user(
206 p_user_id INT
207)
208LANGUAGE plpgsql AS $$
209DECLARE
210 v_count INT;
211BEGIN
212 -- Proverka dali korisnikot postoi
213 IF NOT EXISTS (SELECT 1 FROM "User" WHERE UserID = p_user_id) THEN
214 RAISE EXCEPTION 'Korisnik so ID % ne postoi.', p_user_id;
215 END IF;
216
217 -- Proverka kolku aktivni pretplati ima
218 SELECT COUNT(*) INTO v_count
219 FROM User_Subscription
220 WHERE UserUserID = p_user_id AND Status = 'Active';
221
222 -- Cancel site aktivni pretplati (trigerot ke gi logira site promeni)
223 UPDATE User_Subscription
224 SET Status = 'Cancelled', End_date = CURRENT_DATE
225 WHERE UserUserID = p_user_id AND Status = 'Active';
226
227 -- Izbrishi gi site uredi povrzani so negovite pretplati
228 DELETE FROM Devices
229 WHERE UserSubscriptionID IN (
230 SELECT UserSubscriptionID FROM User_Subscription
231 WHERE UserUserID = p_user_id
232 );
233
234 RAISE NOTICE 'Korisnik % deaktiviran. % pretplati otkazani, uredite izbrishani.', p_user_id, v_count;
235
236 -- Zabeleska: DELETE od "User" ke go aktivira trigger_log_user_delete avtomatski
237
238EXCEPTION
239 WHEN OTHERS THEN
240 RAISE EXCEPTION 'Greshka pri deaktiviranje na korisnik %: %', p_user_id, SQLERRM;
241END;
242$$;
243
244--Зошто би постоела во реален свет:
245--"Cancel my account" на стриминг сервис не брише само еден ред — треба да се откажат претплати, да се отстранат уреди, да се логира се. Процедурата го координира сето тоа, а вашите два постоечки тригери (trigger_log_user_delete и trigger_log_subscription_status_change) автоматски снимаат сe во log табелите.
246
247
248
249
250