-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDatabaseInitializationScript.sql
More file actions
360 lines (321 loc) · 9.88 KB
/
DatabaseInitializationScript.sql
File metadata and controls
360 lines (321 loc) · 9.88 KB
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
######################################################
# Create the database
#######################################################
# Destroy any previously existing database instances.
DROP DATABASE IF EXISTS PairBasedChatRoom;
# Create a new database
CREATE DATABASE PairBasedChatRoom;
USE PairBasedChatRoom;
######################################################
# User defined helper functions for validation
######################################################
# Ensure string is non-empty
DELIMITER //
CREATE PROCEDURE EnsureNonEmpty (string VARCHAR(255), message VARCHAR(255))
BEGIN
If (LENGTH(string) = 0) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = message;
END IF;
END;
//
DELIMITER ;
# Ensure exactly one is NULL.
DELIMITER //
CREATE PROCEDURE EnsureOneIsNull (id1 BIGINT, id2 BIGINT, message VARCHAR(255))
BEGIN
If (id1 > 0 XOR id2 > 0) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = message;
END IF;
END;
//
DELIMITER ;
# Ensure two are not equal (including NULLS)
DELIMITER //
CREATE FUNCTION Same (id1 BIGINT, id2 BIGINT)
RETURNS BOOL
BEGIN
If (id1 > 0 AND id2 > 0) THEN
if(id1 = id2) THEN
RETURN 1;
ELSE
RETURN 0;
END IF;
ELSEIF (id1 > 0 OR id2 > 0) THEN
RETURN 0;
ELSE
RETURN 1;
END IF;
END;
//
DELIMITER ;
######################################################
# Create the tables
#######################################################
# Create the USERS table
CREATE TABLE Users (
id BIGINT NOT NULL UNIQUE AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
username VARCHAR(255) NOT NULL UNIQUE
);
######################################################
# Create the Categories table
#######################################################
DROP TABLE IF EXISTS Categories;
# Create the Categories table
CREATE TABLE Categories (
id BIGINT NOT NULL AUTO_INCREMENT ,
name VARCHAR(255) NOT NULL,
PRIMARY KEY (id),
UNIQUE INDEX idIdx (id ASC)
);
#Add foreign key for parentCategory
ALTER TABLE Categories
ADD COLUMN parent BIGINT,
ADD INDEX parentIdx (parent ASC);
ALTER TABLE Categories
ADD CONSTRAINT parent
FOREIGN KEY (parent)
REFERENCES Categories(id)
ON DELETE CASCADE
ON UPDATE CASCADE;
# Create the Topics table
CREATE TABLE Topics (
id BIGINT NOT NULL UNIQUE AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(255) NOT NULL UNIQUE,
category BIGINT,
statementA VARCHAR(255) NOT NULL,
statementB VARCHAR(255) NOT NULL
);
#Add foreign key for category
ALTER TABLE Topics
ADD INDEX category (category ASC);
ALTER TABLE Topics
ADD CONSTRAINT category
FOREIGN KEY (category)
REFERENCES Categories(id)
ON DELETE CASCADE
ON UPDATE CASCADE;
# Create the SuggestionToChange table
CREATE TABLE SuggestionsToChange (
id BIGINT NOT NULL UNIQUE AUTO_INCREMENT,
categoryToMove BIGINT,
topicToMove BIGINT,
newCategory BIGINT,
CONSTRAINT ctm FOREIGN KEY (categoryToMove)
REFERENCES Categories (id)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT tmp FOREIGN KEY (topicToMove)
REFERENCES Topics(id)
ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT newCategory FOREIGN KEY (id)
REFERENCES Categories (id)
ON DELETE CASCADE ON UPDATE CASCADE
);
# Create the UserVotes table
CREATE TABLE UserVotes (
user BIGINT NOT NULL AUTO_INCREMENT,
suggestionToChange BIGINT NOT NULL,
voteDirection BOOL NOT NULL,
PRIMARY KEY (user , suggestionToChange)
);
ALTER TABLE UserVotes
ADD CONSTRAINT suggestionToChangeFk FOREIGN KEY (suggestionToChange)
REFERENCES SuggestionsToChange(id)
ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD CONSTRAINT userFk FOREIGN KEY (user)
REFERENCES Users(id)
ON DELETE NO ACTION ON UPDATE NO ACTION,
ADD INDEX suggestionToChangeFk (suggestionToChange ASC),
ADD INDEX userFk (user ASC);
# Create Change Comments Table
CREATE TABLE ChangeComments(
suggestionToChangeConversation BIGINT NOT NULL,
creationTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
postContent TEXT NOT NULL,
postedBy BIGINT NOT NULL,
flaggedAsAbusive BOOL NOT NULL DEFAULT 0,
PRIMARY KEY (suggestionToChangeConversation, creationTime),
FOREIGN KEY (suggestionToChangeConversation) REFERENCES SuggestionsToChange(id)
MATCH FULL ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (postedBy) REFERENCES Users(id)
MATCH FULL ON UPDATE CASCADE ON DELETE CASCADE
);
# Create Conversations Table
CREATE TABLE Conversations(
id BIGINT NOT NULL UNIQUE AUTO_INCREMENT PRIMARY KEY,
topic BIGINT NOT NULL,
positionAUser BIGINT,
positionBUser BIGINT,
FOREIGN KEY (topic) REFERENCES Topics(id),
FOREIGN KEY (positionAUser) REFERENCES Users(id),
FOREIGN KEY (positionBUser) REFERENCES Users(id)
);
# Create the ConversationsViewedByUserTracker Tabe
CREATE TABLE ConversationsViewedByUserTracker (
user BIGINT NOT NULL,
conversation BIGINT NOT NULL,
timeConversationWasViewed TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user, conversation, timeConversationWasViewed),
FOREIGN KEY (user) REFERENCES Users(id)
MATCH FULL ON UPDATE CASCADE ON DELETE CASCADE,
FOREIGN KEY (conversation) REFERENCES Conversations(id)
MATCH FULL ON UPDATE CASCADE ON DELETE CASCADE
);
# Create the posts table
CREATE TABLE Posts (
id BIGINT NOT NULL UNIQUE AUTO_INCREMENT PRIMARY KEY,
conversation BIGINT NOT NULL,
creationTime TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
postContent TEXT NOT NULL,
postedBySideA BOOL NOT NULL,
seenByOtherUser BOOL NOT NULL DEFAULT 0,
flaggedAsAbusive BOOL NOT NULL DEFAULT 0,
FOREIGN KEY (conversation) REFERENCES Conversations(id)
MATCH FULL ON UPDATE CASCADE ON DELETE CASCADE
);
######################################################
# Triggers to handle integrety constraints on updates and insertions
######################################################
# Ensure validity of Users
DELIMITER //
CREATE PROCEDURE ValidateUser (email VARCHAR(255), password VARCHAR(255), username VARCHAR(255))
BEGIN
# Reject empty passwords
CALL EnsureNonEmpty(password, 'Password can not be empty.');
# Reject empty usernames
CALL EnsureNonEmpty(username, 'Username can not be empty.');
# The email address must be valid
IF(email NOT REGEXP '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$') THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Email is not valid.';
END IF;
END;
//
DELIMITER ;
# Ensure validity of Topic
DELIMITER //
CREATE PROCEDURE ValidateTopic (name VARCHAR(255), statementA VARCHAR(255), statementB VARCHAR(255))
BEGIN
CALL EnsureNonEmpty(name, 'Topic name can not be empty.');
CALL EnsureNonEmpty(statementA, 'The statement for side A can not be empty.');
CALL EnsureNonEmpty(statementB, 'The statement for side B can not be empty.');
END;
//
DELIMITER ;
# Ensure validity of ChangeCategorySuggestion
DELIMITER //
CREATE PROCEDURE ValidateCategoryChangeSuggestion (categoryToMove BIGINT, topicToMove BIGINT, newCategory BIGINT)
BEGIN
CALL EnsureOneIsNull(categoryToMove, topicToMove, 'Exactly one of categoryToMove and topicToMove must be NULL.');
If(categoryToMove = newCategory) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = "Can not move category to itself.";
END IF;
IF (categoryToMove > 0) THEN
SELECT parent INTO @oldParent FROM Categories WHERE id = categoryToMove;
IF(Same(oldParent, categoryToMove)) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = "Old parent and new parent are the same.";
END IF;
END IF;
END;
//
DELIMITER ;
# On Topic Creation
DELIMITER //
CREATE TRIGGER CreateNewTopic BEFORE INSERT ON Topics
FOR EACH ROW
BEGIN
CALL ValidateTopic(NEW.name, NEW.statementA, NEW.statementB);
END;
//
DELIMITER ;
# On Topic update.
DELIMITER //
CREATE TRIGGER UpdateTopic BEFORE UPDATE ON Topics
FOR EACH ROW
BEGIN
CALL ValidateTopic(NEW.name, NEW.statementA, NEW.statementB);
END;
//
# On User Creation
DELIMITER //
CREATE TRIGGER CreateNewUser BEFORE INSERT ON Users
FOR EACH ROW
BEGIN
CALL ValidateUser(NEW.email, NEW.password, NEW.username);
END;
//
DELIMITER ;
# On User update.
DELIMITER //
CREATE TRIGGER UpdateUser BEFORE UPDATE ON Users
FOR EACH ROW
BEGIN
CALL ValidateUser(NEW.email, NEW.password, NEW.username);
END;
//
DELIMITER ;
# On Category Creation
DELIMITER //
CREATE TRIGGER CreateCategory BEFORE INSERT ON Categories
FOR EACH ROW
BEGIN
CALL EnsureNonEmpty(NEW.name, 'Category name can not be empty.');
END;
//
DELIMITER ;
# On Category Update
DELIMITER //
CREATE TRIGGER UpdateCategory BEFORE UPDATE ON Categories
FOR EACH ROW
BEGIN
CALL EnsureNonEmpty(NEW.name, 'Category name can not be empty.');
END;
//
DELIMITER ;
# On Creation
DELIMITER //
CREATE TRIGGER CreateNewConversation BEFORE INSERT ON Conversations
FOR EACH ROW
BEGIN
If (NEW.positionAUser=NEW.positionBUser) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'positions cannot equal';
END IF;
END;
//
DELIMITER ;
# On update.
DELIMITER //
CREATE TRIGGER UpdateConversation BEFORE UPDATE ON Conversations
FOR EACH ROW
BEGIN
If (NEW.positionAUser=NEW.positionBUser) THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'positions cannot equal';
END IF;
END;
//
DELIMITER ;
# On create SuggestionToChange
DELIMITER //
CREATE TRIGGER CreateSuggestionToChange BEFORE INSERT ON SuggestionsToChange
FOR EACH ROW
BEGIN
CALL ValidateCategoryChangeSuggestion(NEW.categoryToMove, NEW.topicToMove, NEW.newCategory);
END;
//
DELIMITER ;
# On update SuggestionToChange
DELIMITER //
CREATE TRIGGER UpdateSuggestionToChange BEFORE UPDATE ON SuggestionsToChange
FOR EACH ROW
BEGIN
CALL ValidateCategoryChangeSuggestion(NEW.categoryToMove, NEW.topicToMove, NEW.newCategory);
END;
//
DELIMITER ;