-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy path10-2-func-channels.sql
361 lines (317 loc) · 10.9 KB
/
10-2-func-channels.sql
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/*
* Channel Management Functions
* This file contains functions and triggers related to channel operations:
* - Channel creation and membership
* - Channel notifications
* - Member counts and activity tracking
*/
/**
* Function: add_channel_creator_as_admin
* Description: Adds the creator of a new channel as an admin member
* Trigger: Executes after INSERT on public.channels
* Action: Inserts a record into channel_members with ADMIN role for the creator
* Returns: The NEW record (trigger standard)
*/
create or replace function add_channel_creator_as_admin()
returns trigger as $$
begin
-- Insert the channel creator as an admin member
insert into public.channel_members (
channel_id,
member_id,
channel_member_role,
joined_at
)
values (
new.id,
new.created_by,
'ADMIN',
now()
);
return new;
end;
$$ language plpgsql;
comment on function add_channel_creator_as_admin() is
'Adds the creator of a new channel as an admin member in the channel_members table.';
-- Trigger: channel_creator_as_admin
create trigger channel_creator_as_admin
after insert on public.channels
for each row
execute function add_channel_creator_as_admin();
comment on trigger channel_creator_as_admin on public.channels is
'Automatically adds the channel creator as an admin member when a new channel is created.';
/**
* Function: create_channel_notification
* Description: Creates a system notification message when a new channel is created
* Trigger: Executes after INSERT on public.channels
* Action: Creates a notification message in the new channel
* Returns: The NEW record (trigger standard)
*/
create or replace function create_channel_notification()
returns trigger as $$
begin
insert into public.messages (
channel_id,
type,
user_id,
content,
metadata
)
values (
new.id,
'notification',
'992bb85e-78f8-4747-981a-fd63d9317ff1', -- System user ID
'Channel created',
jsonb_build_object(
'type', 'channel_created'
)
);
return new;
end;
$$ language plpgsql;
comment on function create_channel_notification() is
'Creates a system notification message when a new channel is created.';
-- Trigger: notify_channel_creation
create trigger notify_channel_creation
after insert on public.channels
for each row
execute function create_channel_notification();
comment on trigger notify_channel_creation on public.channels is
'Creates a notification message when a new channel is created.';
/* Legacy code - kept for reference but commented out
create or replace function update_last_read_time()
returns trigger as $$
begin
-- Update the last_read_update_at if there's a change in last_read_message_id
if old.last_read_message_id is distinct from new.last_read_message_id then
new.last_read_update_at := timezone('utc', now());
end if;
return new;
end;
$$ language plpgsql;
create trigger trigger_update_last_read_time
before update on public.channel_members
for each row
execute function update_last_read_time();
*/
/**
* Function: notify_channel_name_change
* Description: Creates a system notification when a channel's name is changed
* Trigger: Executes after UPDATE of name on public.channels
* Action: Creates a notification message with the new channel name
* Returns: The NEW record (trigger standard)
*/
create or replace function notify_channel_name_change()
returns trigger as $$
begin
if old.name is distinct from new.name then
insert into public.messages (
channel_id,
type,
user_id,
content,
metadata
)
values (
new.id,
'notification',
'992bb85e-78f8-4747-981a-fd63d9317ff1', -- System user ID
'Channel name was changed to "' || new.name || '"',
jsonb_build_object(
'type', 'channel_name_changed',
'name', new.name
)
);
end if;
return new;
end;
$$ language plpgsql;
comment on function notify_channel_name_change() is
'Creates a system notification message when a channel name is changed.';
-- Trigger: notify_on_channel_name_change
create trigger notify_on_channel_name_change
after update of name on public.channels
for each row
when (old.name is distinct from new.name)
execute function notify_channel_name_change();
comment on trigger notify_on_channel_name_change on public.channels is
'Creates a notification when a channel name is changed.';
/**
* Function: notify_user_join_channel
* Description: Creates a notification message when a user joins a channel
* Trigger: Executes after INSERT on public.channel_members
* Action: Creates a notification message showing who joined
* Returns: The NEW record (trigger standard)
*/
create or replace function notify_user_join_channel()
returns trigger as $$
declare
joining_username text;
begin
-- Get the username of the joining member
select username into joining_username
from public.users
where id = new.member_id;
-- Create the notification message
insert into public.messages (
user_id,
channel_id,
type,
content,
metadata
)
values (
new.member_id,
new.channel_id,
'notification',
joining_username || ' joined the channel',
jsonb_build_object(
'type', 'user_join_channel',
'user_name', joining_username
)
);
return new;
end;
$$ language plpgsql;
comment on function notify_user_join_channel() is
'Creates a notification message when a user joins a channel.';
-- Trigger: notify_on_user_join
create trigger notify_on_user_join
after insert on public.channel_members
for each row
execute function notify_user_join_channel();
comment on trigger notify_on_user_join on public.channel_members is
'Creates a notification when a user joins a channel.';
/**
* Function: notify_user_leave_channel
* Description: Creates a notification message when a user leaves a channel
* Trigger: Executes after DELETE on public.channel_members
* Action: Creates a notification message showing who left
* Returns: The OLD record (trigger standard)
*/
create or replace function notify_user_leave_channel()
returns trigger as $$
declare
leaving_username text;
begin
-- Get the username of the leaving member
select username into leaving_username
from public.users
where id = old.member_id;
-- Check if the channel still exists before creating notification
if exists (select 1 from public.channels where id = old.channel_id) then
insert into public.messages (
user_id,
channel_id,
type,
content,
metadata
)
values (
old.member_id,
old.channel_id,
'notification',
leaving_username || ' left the channel',
jsonb_build_object(
'type', 'user_leave_channel',
'user_name', leaving_username
)
);
end if;
return old;
end;
$$ language plpgsql;
comment on function notify_user_leave_channel() is
'Creates a notification message when a user leaves a channel.';
-- Trigger: notify_on_user_leave
create trigger notify_on_user_leave
after delete on public.channel_members
for each row
execute function notify_user_leave_channel();
comment on trigger notify_on_user_leave on public.channel_members is
'Creates a notification when a user leaves a channel.';
/**
* Function: increment_channel_member_count
* Description: Increments the member_count of a channel when a new member is added
* Trigger: Executes after INSERT on public.channel_members
* Action: Updates the member_count in channels table by adding 1
* Returns: The NEW record (trigger standard)
* Note: Will be rolled back automatically if the transaction is rolled back
*/
create or replace function increment_channel_member_count()
returns trigger as $$
begin
update public.channels
set member_count = member_count + 1
where id = new.channel_id;
return new;
end;
$$ language plpgsql;
comment on function increment_channel_member_count() is
'Increments the member count of a channel when a new member is added.';
-- Trigger: increment_member_count
create trigger increment_member_count
after insert on public.channel_members
for each row
execute function increment_channel_member_count();
comment on trigger increment_member_count on public.channel_members is
'Automatically increments the member count when a new member is added to a channel.';
/**
* Function: decrement_channel_member_count
* Description: Decrements the member_count of a channel when a member is removed
* Trigger: Executes after DELETE on public.channel_members
* Action: Updates the member_count in channels table by subtracting 1
* Returns: The OLD record (trigger standard)
* Note: Will handle member removal from both explicit leave and cascade delete when a user is deleted
*/
create or replace function decrement_channel_member_count()
returns trigger as $$
begin
update public.channels
set member_count = member_count - 1
where id = old.channel_id;
return old;
end;
$$ language plpgsql;
comment on function decrement_channel_member_count() is
'Decrements the member count of a channel when a member is removed.';
-- Trigger: decrement_member_count
create trigger decrement_member_count
after delete on public.channel_members
for each row
execute function decrement_channel_member_count();
comment on trigger decrement_member_count on public.channel_members is
'Automatically decrements the member count when a member is removed from a channel.';
/**
* Function: prevent_duplicate_channel_member
* Description: Prevents adding the same user to a channel multiple times
* Trigger: Executes before INSERT on public.channel_members
* Action: Checks if the user is already a member of the channel and raises exception if true
* Returns: The NEW record (trigger standard) if the user is not already a member
*/
create or replace function prevent_duplicate_channel_member()
returns trigger as $$
begin
-- Check if a record already exists with the same channel_id and member_id
if exists (
select 1
from public.channel_members
where channel_id = new.channel_id
and member_id = new.member_id
) then
-- If exists, raise an exception
raise exception 'This user is already a member of the channel.';
end if;
-- If not, allow the insertion
return new;
end;
$$ language plpgsql;
comment on function prevent_duplicate_channel_member() is
'Prevents adding the same user to a channel multiple times.';
-- Trigger: check_duplicate_member
create trigger check_duplicate_member
before insert on public.channel_members
for each row
execute function prevent_duplicate_channel_member();
comment on trigger check_duplicate_member on public.channel_members is
'Ensures a user cannot be added to the same channel multiple times.';