Half of features implemented #2
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -1,20 +1,19 @@
 | 
			
		|||
package nl.andrewlalis;
 | 
			
		||||
 | 
			
		||||
import nl.andrewlalis.database.Database;
 | 
			
		||||
import nl.andrewlalis.git_api.GithubManager;
 | 
			
		||||
import nl.andrewlalis.model.Student;
 | 
			
		||||
import nl.andrewlalis.model.StudentTeam;
 | 
			
		||||
import nl.andrewlalis.util.CommandLine;
 | 
			
		||||
import nl.andrewlalis.util.FileUtils;
 | 
			
		||||
import nl.andrewlalis.util.Logging;
 | 
			
		||||
import nl.andrewlalis.util.TeamGenerator;
 | 
			
		||||
 | 
			
		||||
import java.io.IOException;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
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 nl.andrewlalis.util.CommandLine;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Main program entry point.
 | 
			
		||||
 */
 | 
			
		||||
| 
						 | 
				
			
			@ -28,16 +27,9 @@ public class Main {
 | 
			
		|||
        Map<String, String> userOptions = CommandLine.parseArgs(args);
 | 
			
		||||
 | 
			
		||||
        // Initialize logger.
 | 
			
		||||
        ConsoleHandler handler = new ConsoleHandler();
 | 
			
		||||
        handler.setLevel(Level.INFO);
 | 
			
		||||
        try {
 | 
			
		||||
            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) {
 | 
			
		||||
            logger.severe("Unable to save log to file.");
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -62,6 +54,16 @@ public class Main {
 | 
			
		|||
            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.util.ArrayList;
 | 
			
		||||
import java.util.List;
 | 
			
		||||
import java.util.Map;
 | 
			
		||||
import java.util.logging.Logger;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +205,18 @@ public class GithubManager {
 | 
			
		|||
        List<GHRepository> repositories = this.organization.listRepositories().asList();
 | 
			
		||||
        for (GHRepository repo : repositories) {
 | 
			
		||||
            if (repo.getName().contains(sub)) {
 | 
			
		||||
                archiveRepository(repo);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * 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();
 | 
			
		||||
| 
						 | 
				
			
			@ -218,9 +229,6 @@ public class GithubManager {
 | 
			
		|||
            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.
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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 {
 | 
			
		||||
        Logger logger = Logger.getGlobal();
 | 
			
		||||
 | 
			
		||||
        if (verbose) {
 | 
			
		||||
            logger.setLevel(Level.FINEST);
 | 
			
		||||
        } else {
 | 
			
		||||
            logger.setLevel(Level.INFO);
 | 
			
		||||
        Handler[] handlers = logger.getHandlers();
 | 
			
		||||
        for (Handler h : handlers) {
 | 
			
		||||
            logger.removeHandler(h);
 | 
			
		||||
        }
 | 
			
		||||
        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");
 | 
			
		||||
        formatter = new SimpleFormatter();
 | 
			
		||||
 | 
			
		||||
        outputFile.setFormatter(formatter);
 | 
			
		||||
        outputFile.setLevel(Level.FINEST);
 | 
			
		||||
        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