Added ON UPDATE to FK relations

main
noah metz 2024-01-31 23:43:12 -07:00
parent 88293f86b0
commit 32f520005a
1 changed files with 132 additions and 32 deletions

@ -69,21 +69,36 @@ init_db(Database) ->
{division, text}, {division, text},
{other, text}], {other, text}],
[{primary_key, [field]}, [{primary_key, [field]},
{foreign_key, {[division], divisions, [division], "ON DELETE SET NULL"}}, % Clear divisions that are deleted
{foreign_key, {[division],
divisions,
[division],
"ON DELETE SET NULL
ON UPDATE CASCADE"}},
{check, "other IN ('testing', 'skills')"}]), {check, "other IN ('testing', 'skills')"}]),
ok = sqlite3:create_table(Database, teams, [{team, text, [not_null]}, ok = sqlite3:create_table(Database, teams, [{team, text, [not_null]},
{division, text}, {division, text},
{inspection, blob}], {inspection, blob}],
[{primary_key, [team]}, [{primary_key, [team]},
{foreign_key, {[division], divisions, [division], "ON DELETE SET NULL"}}]), % Clear divisions that are deleted
{foreign_key, {[division],
divisions,
[division],
"ON DELETE SET NULL
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, matches, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, matches, [{division, text, [not_null]},
{type, text, [not_null]}, {type, text, [not_null]},
{number, integer, [not_null]}], {number, integer, [not_null]}],
[{primary_key, [division, type, number]}, [{primary_key, [division, type, number]},
{check, "type IN ('practice', 'qualification')"}, {check, "type IN ('practice', 'qualification')"},
{foreign_key, {[division], divisions, [division], "ON DELETE CASCADE"}}]), % Delete matches when division deleted
{foreign_key, {[division],
divisions,
[division],
"ON DELETE CASCADE
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, match_states, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, match_states, [{division, text, [not_null]},
{type, text, [not_null]}, {type, text, [not_null]},
@ -91,7 +106,12 @@ init_db(Database) ->
{tick, integer, [not_null]}, {tick, integer, [not_null]},
{state, text, [not_null]}], {state, text, [not_null]}],
[{primary_key, [division, type, number, tick]}, [{primary_key, [division, type, number, tick]},
{foreign_key, {[division, type, number], matches, [division, type, number], "ON DELETE CASCADE"}}]), % Delete states when match deleted
{foreign_key, {[division, type, number],
matches,
[division, type, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, match_teams, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, match_teams, [{division, text, [not_null]},
{type, text, [not_null]}, {type, text, [not_null]},
@ -103,8 +123,18 @@ init_db(Database) ->
{check, "side IN ('red', 'blue')"}, {check, "side IN ('red', 'blue')"},
{check, "anum >= 1 AND anum <= 2"}, {check, "anum >= 1 AND anum <= 2"},
{check, "type IN ('practice', 'qualification')"}, {check, "type IN ('practice', 'qualification')"},
{foreign_key, {[division, type, number], matches, [division, type, number], "ON DELETE CASCADE"}}, % Delete team associations when match deleted
{foreign_key, {[team], teams, [team], ""}}]), {foreign_key, {[division, type, number],
matches,
[division, type, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}},
% Restrict team from being deleted that's associated with a match
{foreign_key, {[team],
teams,
[team],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, match_scores, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, match_scores, [{division, text, [not_null]},
{type, text, [not_null]}, {type, text, [not_null]},
@ -112,54 +142,103 @@ init_db(Database) ->
{history, integer, [not_null]}, {history, integer, [not_null]},
{uuid, integer, [not_null]}], {uuid, integer, [not_null]}],
[{primary_key, [division, type, number, history]}, [{primary_key, [division, type, number, history]},
{foreign_key, {[uuid], scores, [uuid], "ON DELETE CASCADE"}}, % Restrict scores from being deleted that are referenced
{foreign_key, {[uuid],
scores,
[uuid],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}},
% Restrict matches from being deleted that are scored
{foreign_key, {[division, type, number], {foreign_key, {[division, type, number],
matches, matches,
[division, type, number], [division, type, number],
"ON DELETE CASCADE"}}]), "ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, brackets, [{division, text}, ok = sqlite3:create_table(Database, brackets, [{division, text},
{stage, integer, [not_null]},
{number, integer, [not_null]}], {number, integer, [not_null]}],
[{primary_key, [division, number]}, [{primary_key, [division, stage, number]},
{foreign_key, {[division], divisions, [division], "ON DELETE CASCADE"}}]), % Delete brackets when division deleted
{foreign_key, {[division],
divisions,
[division],
"ON DELETE CASCADE
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, bracket_states, [{division, text}, ok = sqlite3:create_table(Database, bracket_states, [{division, text},
{stage, integer, [not_null]},
{number, integer, [not_null]}, {number, integer, [not_null]},
{tick, integer, [not_null]}, {tick, integer, [not_null]},
{state, text, [not_null]}], {state, text, [not_null]}],
[{primary_key, [division, number, tick]}, [{primary_key, [division, stage, number, tick]},
{foreign_key, {[division, number], brackets, [division, number], "ON DELETE CASCADE"}}]), % Delete states when bracket deleted
{foreign_key, {[division, stage, number],
brackets,
[division, stage, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, elimination_alliances, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, elimination_alliances, [{division, text, [not_null]},
{stage, integer, [not_null]},
{number, integer, [not_null]}, {number, integer, [not_null]},
{side, text, [not_null]}, {side, text, [not_null]},
{anum, integer, [not_null]}], {anum, integer, [not_null]}],
[{primary_key, [division, number, side]}, [{primary_key, [division, stage, number, side]},
{check, "side IN ('red', 'blue')"}, {check, "side IN ('red', 'blue')"},
{foreign_key, {[division, number], brackets, [division, number], "ON DELETE CASCADE"}}, % Delete alliance associations when bracket deleted
{foreign_key, {[division, anum], alliances, [division, number], ""}}]), {foreign_key, {[division, stage, number],
brackets,
[division, stage, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}},
% Restrict alliance from being deleted that's associated with a bracket
{foreign_key, {[division, anum],
alliances,
[division, number],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, finals_alliances, [{division, text}, ok = sqlite3:create_table(Database, finals_alliances, [{division, text},
{stage, integer, [not_null]},
{number, integer, [not_null]}, {number, integer, [not_null]},
{side, text, [not_null]}, {side, text, [not_null]},
{adiv, text, [not_null]}], {adiv, text, [not_null]}],
[{primary_key, [division, number, side]}, [{primary_key, [division, stage, number, side]},
{check, "side IN ('red', 'blue')"}, {check, "side IN ('red', 'blue')"},
{check, "division IS NULL"}, {check, "division IS NULL"},
{foreign_key, {[division, number], brackets, [division, number], "ON DELETE CASCADE"}}, % Delete alliance associations when bracket deleted
{foreign_key, {[adiv], winners, [division], ""}}]), {foreign_key, {[division, stage, number],
brackets,
[division, stage, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}},
% Restrict winners from being deleted that's associated with a bracket
{foreign_key, {[adiv],
winners,
[division],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, bracket_scores, [{division, text}, ok = sqlite3:create_table(Database, bracket_scores, [{division, text},
{stage, integer, [not_null]},
{number, integer, [not_null]}, {number, integer, [not_null]},
{instance, integer, [not_null]}, {instance, integer, [not_null]},
{history, integer, [not_null]}, {history, integer, [not_null]},
{uuid, integer, [not_null]}], {uuid, integer, [not_null]}],
[{primary_key, [division, number, instance, history]}, [{primary_key, [division, number, instance, history]},
{foreign_key, {[uuid], scores, [uuid], "ON DELETE CASCADE"}}, % Restrict scores from being deleted that are referenced
{foreign_key, {[division, number], {foreign_key, {[uuid],
scores,
[uuid],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}},
% Restrict brackets from being deleted that are scored
{foreign_key, {[division, stage, number],
brackets, brackets,
[division, number], [division, stage, number],
"ON DELETE CASCADE"}}]), "ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, scores, [{uuid, integer, [not_null]}, ok = sqlite3:create_table(Database, scores, [{uuid, integer, [not_null]},
{autonomous, integer, [not_null]}, {autonomous, integer, [not_null]},
@ -188,20 +267,40 @@ init_db(Database) ->
ok = sqlite3:create_table(Database, alliances, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, alliances, [{division, text, [not_null]},
{number, integer, [not_null]}], {number, integer, [not_null]}],
[{primary_key, [division, number]}, [{primary_key, [division, number]},
{foreign_key, {[division], divisions, [division], "ON DELETE CASCADE"}}]), % Delete alliances when deleting division
{foreign_key, {[division],
divisions,
[division],
"ON DELETE CASCADE
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, alliance_members, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, alliance_members, [{division, text, [not_null]},
{number, integer, [not_null]}, {number, integer, [not_null]},
{anum, integer, [not_null]}, {anum, integer, [not_null]},
{team, text, [not_null]}], {team, text, [not_null]}],
[{primary_key, [division, number, anum]}, [{primary_key, [division, number, anum]},
{foreign_key, {[division, number], alliances, [division, number], "ON DELETE CASCADE"}}, % Delete alliance members when deleting alliances
{foreign_key, {[team], teams, [team], "ON DELETE CASCADE"}}]), {foreign_key, {[division, number],
alliances,
[division, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}},
% Restrict teams being deleted that are in alliances
{foreign_key, {[team],
teams,
[team],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, winners, [{division, text, [not_null]}, ok = sqlite3:create_table(Database, winners, [{division, text, [not_null]},
{alliance, integer, [not_null]}], {alliance, integer, [not_null]}],
[{primary_key, [division]}, [{primary_key, [division]},
{foreign_key, {[division, alliance], alliances, [division, number], "ON DELETE CASCADE"}}]), % Restrict divisions from being deleted that have winners
{foreign_key, {[division, alliance],
alliances,
[division, number],
"ON DELETE CASCADE
ON UPDATE CASCADE"}}]),
ok = sqlite3:create_table(Database, skills_scores, [{team, text, [not_null]}, ok = sqlite3:create_table(Database, skills_scores, [{team, text, [not_null]},
{type, text, [not_null]}, {type, text, [not_null]},
@ -213,7 +312,12 @@ init_db(Database) ->
{azone, integer, [not_null]}], {azone, integer, [not_null]}],
[{primary_key, [team, type, attempt]}, [{primary_key, [team, type, attempt]},
{check, "type IN ('driver', 'autonomous')"}, {check, "type IN ('driver', 'autonomous')"},
{foreign_key, {[team], teams, [team], ""}}]), % Prevent teams being deleted that have skills scores
{foreign_key, {[team],
teams,
[team],
"ON DELETE RESTRICT
ON UPDATE CASCADE"}}]),
ok. ok.
delete_teams(Database, Teams) -> delete_teams(Database, Teams) ->
@ -405,11 +509,7 @@ handle_call({generate_elimination, Division, Size}, _, State) ->
io_lib:format("DELETE FROM brackets WHERE division = '~s'; ", [Division]), io_lib:format("DELETE FROM brackets WHERE division = '~s'; ", [Division]),
lists:append([io_lib:format("INSERT INTO alliances(division, number) VALUES('~s', ~p); ", lists:append([io_lib:format("INSERT INTO alliances(division, number) VALUES('~s', ~p); ",
[Division, N]) [Division, N])
|| N <- lists:seq(1, Size)]), || N <- lists:seq(1, Size)])]),
lists:append([io_lib:format("INSERT INTO brackets(division, number)
VALUES('~s', ~p);",
[Division, N])
|| N <- lists:seq(1, Size-1)])]),
{reply, sql_begin(State#state.database, SQL), State}; {reply, sql_begin(State#state.database, SQL), State};
handle_call(generate_finals, _, State) -> handle_call(generate_finals, _, State) ->