Started database support.
This commit is contained in:
parent
e901b0affd
commit
b7a89c0946
|
@ -1,20 +1,19 @@
|
||||||
package nl.andrewlalis;
|
package nl.andrewlalis;
|
||||||
|
|
||||||
|
import nl.andrewlalis.database.Database;
|
||||||
import nl.andrewlalis.git_api.GithubManager;
|
import nl.andrewlalis.git_api.GithubManager;
|
||||||
|
import nl.andrewlalis.model.Student;
|
||||||
import nl.andrewlalis.model.StudentTeam;
|
import nl.andrewlalis.model.StudentTeam;
|
||||||
|
import nl.andrewlalis.util.CommandLine;
|
||||||
|
import nl.andrewlalis.util.FileUtils;
|
||||||
import nl.andrewlalis.util.Logging;
|
import nl.andrewlalis.util.Logging;
|
||||||
import nl.andrewlalis.util.TeamGenerator;
|
import nl.andrewlalis.util.TeamGenerator;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.ConsoleHandler;
|
|
||||||
import java.util.logging.Handler;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import nl.andrewlalis.util.CommandLine;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Main program entry point.
|
* Main program entry point.
|
||||||
*/
|
*/
|
||||||
|
@ -28,16 +27,9 @@ public class Main {
|
||||||
Map<String, String> userOptions = CommandLine.parseArgs(args);
|
Map<String, String> userOptions = CommandLine.parseArgs(args);
|
||||||
|
|
||||||
// Initialize logger.
|
// Initialize logger.
|
||||||
ConsoleHandler handler = new ConsoleHandler();
|
|
||||||
handler.setLevel(Level.INFO);
|
|
||||||
try {
|
try {
|
||||||
Logging.setup(true); // TODO: Replace true with command line arg.
|
Logging.setup(true); // TODO: Replace true with command line arg.
|
||||||
Handler[] handlers = logger.getHandlers();
|
|
||||||
for (Handler h : handlers) {
|
|
||||||
logger.removeHandler(h);
|
|
||||||
}
|
|
||||||
logger.setUseParentHandlers(false);
|
|
||||||
logger.addHandler(handler);
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
logger.severe("Unable to save log to file.");
|
logger.severe("Unable to save log to file.");
|
||||||
}
|
}
|
||||||
|
@ -62,6 +54,16 @@ public class Main {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Initialize database.
|
||||||
|
Database db = new Database("database/initializer.sqlite");
|
||||||
|
db.initialize();
|
||||||
|
for (StudentTeam team : studentTeams) {
|
||||||
|
for (Student student : team.getStudents()) {
|
||||||
|
db.storeStudent(student);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,159 @@
|
||||||
|
package nl.andrewlalis.database;
|
||||||
|
|
||||||
|
import nl.andrewlalis.model.Person;
|
||||||
|
import nl.andrewlalis.model.Student;
|
||||||
|
import nl.andrewlalis.model.TeachingAssistant;
|
||||||
|
import nl.andrewlalis.util.FileUtils;
|
||||||
|
|
||||||
|
import java.sql.*;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class abstracts many of the functions needed for interaction with the application's SQLite database.
|
||||||
|
*/
|
||||||
|
public class Database {
|
||||||
|
|
||||||
|
private static final int PERSON_TYPE_STUDENT = 0;
|
||||||
|
private static final int PERSON_TYPE_TA = 1;
|
||||||
|
|
||||||
|
private static final int TEAM_TYPE_STUDENT = 0;
|
||||||
|
private static final int TEAM_TYPE_TA = 1;
|
||||||
|
private static final int TEAM_TYPE_TA_ALL = 2;
|
||||||
|
|
||||||
|
private static final int TEAM_NONE = 0;
|
||||||
|
private static final int TEAM_TA_ALL = 1;
|
||||||
|
|
||||||
|
private static final int ERROR_TYPE_TEAM = 0;
|
||||||
|
private static final int ERROR_TYPE_PERSON = 1;
|
||||||
|
private static final int ERROR_TYPE_SYSTEM = 2;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The connection needed for all queries.
|
||||||
|
*/
|
||||||
|
private Connection connection;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The logger for outputting debug info.
|
||||||
|
*/
|
||||||
|
private static final Logger logger = Logger.getLogger(Database.class.getName());
|
||||||
|
static {
|
||||||
|
logger.setParent(Logger.getGlobal());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Database(String databaseFilename) {
|
||||||
|
try {
|
||||||
|
this.connection = DriverManager.getConnection("jdbc:sqlite:" + databaseFilename);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the database from the table_init.sql script, which defines the table schema and starting data.
|
||||||
|
* @return True, if successful, false if not.
|
||||||
|
*/
|
||||||
|
public boolean initialize() {
|
||||||
|
String sql = FileUtils.readStringFromFile("/sql/table_init.sql");
|
||||||
|
String[] commands = sql.split(";");
|
||||||
|
for (String command : commands) {
|
||||||
|
logger.finest("Executing command: " + command);
|
||||||
|
if (command.trim().length() > 1) {
|
||||||
|
try {
|
||||||
|
PreparedStatement statement = this.connection.prepareStatement(command);
|
||||||
|
statement.execute();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
logger.severe("SQLException: " + e.getErrorCode());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.fine("Database initialized.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a person in the database.
|
||||||
|
* @param person The person object to store.
|
||||||
|
* @param personType The type of person to store, using a constant defined above.
|
||||||
|
* @return True if successful, false otherwise.
|
||||||
|
*/
|
||||||
|
private boolean storePerson(Person person, int personType) {
|
||||||
|
try {
|
||||||
|
String sql = "INSERT INTO persons (id, name, email_address, github_username, person_type_id) VALUES (?, ?, ?, ?, ?);";
|
||||||
|
PreparedStatement stmt = this.connection.prepareStatement(sql);
|
||||||
|
stmt.setInt(1, person.getNumber());
|
||||||
|
stmt.setString(2, person.getName());
|
||||||
|
stmt.setString(3, person.getEmailAddress());
|
||||||
|
stmt.setString(4, person.getGithubUsername());
|
||||||
|
stmt.setInt(5, personType);
|
||||||
|
return stmt.execute();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a teaching assistant without a team.
|
||||||
|
* @param ta The teaching assistant to store.
|
||||||
|
* @return True if successful, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean storeTeachingAssistant(TeachingAssistant ta) {
|
||||||
|
return this.storeTeachingAssistant(ta, TEAM_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a teaching assistant in the database.
|
||||||
|
* @param ta The teaching assistant to store.
|
||||||
|
* @param teamId The teaching assistant's team id.
|
||||||
|
* @return True if successful, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean storeTeachingAssistant(TeachingAssistant ta, int teamId) {
|
||||||
|
if (!storePerson(ta, PERSON_TYPE_TA)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String sql = "INSERT INTO teaching_assistants (person_id, team_id) VALUES (?, ?);";
|
||||||
|
PreparedStatement stmt = this.connection.prepareStatement(sql);
|
||||||
|
stmt.setInt(1, ta.getNumber());
|
||||||
|
stmt.setInt(2, teamId);
|
||||||
|
return stmt.execute();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a student without a team.
|
||||||
|
* @param student The student to store.
|
||||||
|
* @return True if successful, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean storeStudent(Student student) {
|
||||||
|
return this.storeStudent(student, TEAM_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores a student in the database.
|
||||||
|
* @param student The student to store.
|
||||||
|
* @param teamId The team id for the team the student is in.
|
||||||
|
* @return True if the operation was successful, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean storeStudent(Student student, int teamId) {
|
||||||
|
if (!storePerson(student, PERSON_TYPE_STUDENT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String sql = "INSERT INTO students (person_id, team_id, chose_partner) VALUES (?, ?, ?);";
|
||||||
|
PreparedStatement stmt = this.connection.prepareStatement(sql);
|
||||||
|
stmt.setInt(1, student.getNumber());
|
||||||
|
stmt.setInt(2, teamId);
|
||||||
|
stmt.setInt(3, student.getPreferredPartners().size() > 0 ? 1 : 0);
|
||||||
|
return stmt.execute();
|
||||||
|
} catch (SQLException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,7 +14,6 @@ import org.kohsuke.github.*;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -206,21 +205,30 @@ public class GithubManager {
|
||||||
List<GHRepository> repositories = this.organization.listRepositories().asList();
|
List<GHRepository> repositories = this.organization.listRepositories().asList();
|
||||||
for (GHRepository repo : repositories) {
|
for (GHRepository repo : repositories) {
|
||||||
if (repo.getName().contains(sub)) {
|
if (repo.getName().contains(sub)) {
|
||||||
HttpPatch patch = new HttpPatch("https://api.github.com/repos/" + repo.getFullName() + "?access_token=" + this.accessToken);
|
archiveRepository(repo);
|
||||||
CloseableHttpClient client = HttpClientBuilder.create().build();
|
|
||||||
ObjectMapper mapper = new ObjectMapper();
|
|
||||||
ObjectNode root = mapper.createObjectNode();
|
|
||||||
root.put("archived", true);
|
|
||||||
String json = mapper.writeValueAsString(root);
|
|
||||||
patch.setEntity(new StringEntity(json));
|
|
||||||
HttpResponse response = client.execute(patch);
|
|
||||||
if (response.getStatusLine().getStatusCode() != 200) {
|
|
||||||
throw new IOException("Could not archive repository: " + repo.getName() + ". Code: " + response.getStatusLine().getStatusCode());
|
|
||||||
}
|
|
||||||
logger.info("Archived repository: " + repo.getFullName());
|
|
||||||
// TODO: archive repository using Github Java API, instead of Apache HttpUtils.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Archives a repository so that it can no longer be manipulated.
|
||||||
|
* TODO: Change to using Github API instead of Apache HttpUtils.
|
||||||
|
* @param repo The repository to archive.
|
||||||
|
* @throws IOException If an error occurs with the HTTP request.
|
||||||
|
*/
|
||||||
|
public void archiveRepository(GHRepository repo) throws IOException {
|
||||||
|
HttpPatch patch = new HttpPatch("https://api.github.com/repos/" + repo.getFullName() + "?access_token=" + this.accessToken);
|
||||||
|
CloseableHttpClient client = HttpClientBuilder.create().build();
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
ObjectNode root = mapper.createObjectNode();
|
||||||
|
root.put("archived", true);
|
||||||
|
String json = mapper.writeValueAsString(root);
|
||||||
|
patch.setEntity(new StringEntity(json));
|
||||||
|
HttpResponse response = client.execute(patch);
|
||||||
|
if (response.getStatusLine().getStatusCode() != 200) {
|
||||||
|
throw new IOException("Could not archive repository: " + repo.getName() + ". Code: " + response.getStatusLine().getStatusCode());
|
||||||
|
}
|
||||||
|
logger.info("Archived repository: " + repo.getFullName());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ public class Student extends Person {
|
||||||
* @param emailAddress The student's email address.
|
* @param emailAddress The student's email address.
|
||||||
* @param githubUsername The student's github username.
|
* @param githubUsername The student's github username.
|
||||||
* @param preferredPartners A list of this student's preferred partners, as a list of integers representing the
|
* @param preferredPartners A list of this student's preferred partners, as a list of integers representing the
|
||||||
* other students' numbers.
|
* other students' numbers.
|
||||||
*/
|
*/
|
||||||
public Student(int number, String name, String emailAddress, String githubUsername, List<Integer> preferredPartners) {
|
public Student(int number, String name, String emailAddress, String githubUsername, List<Integer> preferredPartners) {
|
||||||
super(number, name, emailAddress, githubUsername);
|
super(number, name, emailAddress, githubUsername);
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package nl.andrewlalis.util;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains some methods which come in handy in lots of other places.
|
||||||
|
*/
|
||||||
|
public class FileUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the contents of the file specified by the filename into a String.
|
||||||
|
* @param filename The filename to read the file of, either relative or absolute.
|
||||||
|
* @return A string containing the file's contents.
|
||||||
|
*/
|
||||||
|
public static String readStringFromFile(String filename) {
|
||||||
|
try (BufferedReader r = new BufferedReader(new InputStreamReader(FileUtils.class.getResourceAsStream(filename)))) {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while ((line = r.readLine()) != null) {
|
||||||
|
sb.append(line).append('\n');
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -14,16 +14,26 @@ public class Logging {
|
||||||
public static void setup(boolean verbose) throws IOException {
|
public static void setup(boolean verbose) throws IOException {
|
||||||
Logger logger = Logger.getGlobal();
|
Logger logger = Logger.getGlobal();
|
||||||
|
|
||||||
if (verbose) {
|
Handler[] handlers = logger.getHandlers();
|
||||||
logger.setLevel(Level.FINEST);
|
for (Handler h : handlers) {
|
||||||
} else {
|
logger.removeHandler(h);
|
||||||
logger.setLevel(Level.INFO);
|
|
||||||
}
|
}
|
||||||
|
logger.setUseParentHandlers(false);
|
||||||
|
|
||||||
|
ConsoleHandler handler = new ConsoleHandler();
|
||||||
|
if (verbose) {
|
||||||
|
handler.setLevel(Level.FINEST);
|
||||||
|
} else {
|
||||||
|
handler.setLevel(Level.INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.addHandler(handler);
|
||||||
|
|
||||||
outputFile = new FileHandler("log/latest.txt");
|
outputFile = new FileHandler("log/latest.txt");
|
||||||
formatter = new SimpleFormatter();
|
formatter = new SimpleFormatter();
|
||||||
|
|
||||||
outputFile.setFormatter(formatter);
|
outputFile.setFormatter(formatter);
|
||||||
|
outputFile.setLevel(Level.FINEST);
|
||||||
logger.addHandler(outputFile);
|
logger.addHandler(outputFile);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
INSERT INTO persons (id, name, email_address, github_username, person_type_id)
|
||||||
|
VALUES (?, ?, ?, ?, ?);
|
|
@ -0,0 +1,150 @@
|
||||||
|
PRAGMA foreign_keys = TRUE;
|
||||||
|
PRAGMA writable_schema = 1;
|
||||||
|
DELETE FROM sqlite_master WHERE type IN ('table', 'index', 'trigger');
|
||||||
|
PRAGMA writable_schema = 0;
|
||||||
|
VACUUM;
|
||||||
|
|
||||||
|
-- Basic schema design.
|
||||||
|
CREATE TABLE IF NOT EXISTS person_types (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO person_types (id, name)
|
||||||
|
VALUES (0, 'student'),
|
||||||
|
(1, 'teaching-assistant'),
|
||||||
|
(2, 'professor');
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS persons (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
email_address TEXT NOT NULL,
|
||||||
|
github_username TEXT NOT NULL UNIQUE,
|
||||||
|
person_type_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (person_type_id)
|
||||||
|
REFERENCES person_types(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS team_types (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO team_types (id, name)
|
||||||
|
VALUES (0, 'student_team'),
|
||||||
|
(1, 'teaching_assistant_team'),
|
||||||
|
(2, 'all_teaching_assistants'),
|
||||||
|
(3, 'none');
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS teams (
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
team_type_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (team_type_id)
|
||||||
|
REFERENCES team_types(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO teams (id, team_type_id)
|
||||||
|
VALUES (0, 3), -- None team for all students or TA's without a team.
|
||||||
|
(1, 2); -- Team for all teaching assistants.
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS teaching_assistant_teams (
|
||||||
|
team_id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE,
|
||||||
|
FOREIGN KEY (team_id)
|
||||||
|
REFERENCES teams(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS student_teams (
|
||||||
|
team_id INTEGER PRIMARY KEY,
|
||||||
|
repository_name TEXT,
|
||||||
|
group_id INTEGER NOT NULL UNIQUE,
|
||||||
|
teaching_assistant_team_id INTEGER,
|
||||||
|
FOREIGN KEY (team_id)
|
||||||
|
REFERENCES teams(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (teaching_assistant_team_id)
|
||||||
|
REFERENCES teaching_assistant_teams(team_id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS students (
|
||||||
|
person_id INTEGER PRIMARY KEY,
|
||||||
|
team_id INTEGER NOT NULL,
|
||||||
|
chose_partner INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (person_id)
|
||||||
|
REFERENCES persons(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (team_id)
|
||||||
|
REFERENCES teams(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS teaching_assistants (
|
||||||
|
person_id INTEGER PRIMARY KEY,
|
||||||
|
team_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (person_id)
|
||||||
|
REFERENCES persons(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (team_id)
|
||||||
|
REFERENCES teams(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Error queue storage.
|
||||||
|
CREATE TABLE IF NOT EXISTS error_types (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO error_types (id, name)
|
||||||
|
VALUES (0, 'team_error'),
|
||||||
|
(1, 'person_error'),
|
||||||
|
(2, 'system_error');
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS errors (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
timestamp DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
error_type_id INTEGER NOT NULL,
|
||||||
|
message TEXT NOT NULL,
|
||||||
|
FOREIGN KEY (error_type_id)
|
||||||
|
REFERENCES error_types(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS team_errors (
|
||||||
|
error_id INTEGER PRIMARY KEY,
|
||||||
|
team_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (error_id)
|
||||||
|
REFERENCES errors(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (team_id)
|
||||||
|
REFERENCES teams(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS person_errors (
|
||||||
|
error_id INTEGER PRIMARY KEY,
|
||||||
|
person_id INTEGER NOT NULL,
|
||||||
|
FOREIGN KEY (error_id)
|
||||||
|
REFERENCES errors(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE,
|
||||||
|
FOREIGN KEY (person_id)
|
||||||
|
REFERENCES persons(id)
|
||||||
|
ON DELETE CASCADE
|
||||||
|
ON UPDATE CASCADE
|
||||||
|
);
|
Loading…
Reference in New Issue