Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,32 @@
import java.nio.file.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

import lombok.extern.slf4j.Slf4j;
import net.discordjug.javabot.data.h2db.commands.MigrationsListSubcommand;

/**
* Utility class that handles SQL Migrations.
*/
@Slf4j
public class MigrationUtils {

private static final Path migrationDirectory;

private MigrationUtils() {
}

static {
Path dir;
try {
dir = createMigrationsDirectory();
} catch (IOException | URISyntaxException e) {
log.error("Cannot create database migration directory", e);
dir = null;
}
migrationDirectory = dir;
}

/**
* Tries to get the Migrations Directories' Path.
Expand All @@ -26,6 +42,10 @@ private MigrationUtils() {
* @throws IOException If an error occurs.
*/
public static Path getMigrationsDirectory() throws URISyntaxException, IOException {
return Objects.requireNonNull(migrationDirectory);
}

private static Path createMigrationsDirectory() throws IOException, URISyntaxException {
URL resource = MigrationsListSubcommand.class.getResource("/database/migrations/");
if (resource == null) throw new IOException("Missing resource /migrations/");
URI uri = resource.toURI();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public ExportTableSubcommand(ExecutorService asyncPool, SystemsConfig systemsCon
.addChoice("Message Cache", "MESSAGE_CACHE")
.addChoice("Question of the Week Accounts", "QOTW_POINTS")
.addChoice("Question of the Week Questions", "QOTW_QUESTION")
.addChoice("Reserved Help Channels", "RESERVED_HELP_CHANNELS")
.addChoice("Starboard", "STARBOARD")
.addChoice("Warns", "WARN")
.addChoice("User Preferences", "USER_PREFERENCES"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ public void execute(@NotNull SlashCommandInteractionEvent event) {
return;
}
String sql = Files.readString(migrationFile);
migrationsDir.getFileSystem().close();
String[] statements = sql.split("\\s*;\\s*");
if (statements.length == 0) {
Responses.error(event, "The migration `" + migrationName + "` does not contain any statements. Please remove or edit it before running again.").queue();
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

37 changes: 0 additions & 37 deletions src/main/resources/database/migrations/09-08-2025_forms.sql

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

7 changes: 7 additions & 0 deletions src/main/resources/database/migrations/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Creating database migrations

To create a database migration, first create a migration script containing the change you want to perform. This script should be located in this directory (`src/main/resources/database/migrations`) and use a file name in the format `yyyy-MM-dd_<name>.sql` where `<name>` is a short name/description of the database migration. An example of such a file name would be `1970-01-01_create-the-world.sql`.

After creating the database script, verify that it works using the `/db-admin migrate <your script>` command.

Finally, add your change to the `src/main/resources/database/schema.sql` file.
69 changes: 57 additions & 12 deletions src/main/resources/database/schema.sql
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
// Help System
CREATE TABLE IF NOT EXISTS reserved_help_channels
(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
channel_id BIGINT NOT NULL UNIQUE,
reserved_at TIMESTAMP(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0),
user_id BIGINT NOT NULL,
timeout INT NOT NULL DEFAULT 60
);

CREATE TABLE IF NOT EXISTS help_channel_thanks
(
id BIGINT PRIMARY KEY AUTO_INCREMENT,
Expand All @@ -31,7 +22,7 @@ CREATE TABLE IF NOT EXISTS help_transaction
recipient BIGINT NOT NULL,
created_at TIMESTAMP(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
weight DOUBLE NOT NULL,
messagetype INT NOT NULL DEFAULT 0
channel BIGINT DEFAULT -1
);

// Question of the Week
Expand Down Expand Up @@ -95,13 +86,14 @@ CREATE TABLE IF NOT EXISTS message_cache
(
message_id BIGINT PRIMARY KEY,
author_id BIGINT NOT NULL,
message_content VARCHAR(4000) NOT NULL
message_content VARCHAR(4000) NOT NULL,
channel_id BIGINT DEFAULT -1
);

CREATE TABLE IF NOT EXISTS message_cache_attachments (
message_id BIGINT NOT NULL,
attachment_index INT NOT NULL,
link VARCHAR(255),
link VARCHAR(511),
PRIMARY KEY(message_id, attachment_index)
);

Expand All @@ -120,3 +112,56 @@ CREATE TABLE qotw_champion (
user_id BIGINT NOT NULL,
PRIMARY KEY(guild_id, user_id)
);

// staff activity
CREATE TABLE staff_activity_messages (
guild_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
message_id BIGINT NOT NULL,
PRIMARY KEY(guild_id, user_id)
);

// custom voice channels
CREATE TABLE custom_vc (
channel_id BIGINT NOT NULL PRIMARY KEY,
owner_id BIGINT NOT NULL
);

// forms
CREATE TABLE forms (
form_id BIGINT NOT NULL AUTO_INCREMENT,
title VARCHAR NOT NULL,
submit_message VARCHAR DEFAULT NULL,
submit_channel BIGINT NOT NULL,
message_id BIGINT DEFAULT NULL,
message_channel BIGINT DEFAULT NULL,
expiration TIMESTAMP DEFAULT NULL,
closed BOOLEAN NOT NULL DEFAULT FALSE,
onetime BOOLEAN NOT NULL DEFAULT FALSE,
PRIMARY KEY (form_id)
);

CREATE TABLE form_fields (
id BIGINT NOT NULL AUTO_INCREMENT,
form_id BIGINT NOT NULL,
label VARCHAR NOT NULL,
min INTEGER DEFAULT 0 NOT NULL,
max INTEGER DEFAULT 16 NOT NULL,
placeholder VARCHAR,
"required" BOOLEAN DEFAULT FALSE NOT NULL,
"style" ENUM('SHORT', 'PARAGRAPH') DEFAULT 'SHORT' NOT NULL,
initial VARCHAR DEFAULT NULL,
PRIMARY KEY (id),
FOREIGN KEY (form_id) REFERENCES forms(form_id) ON DELETE CASCADE ON UPDATE RESTRICT
);

CREATE TABLE form_submissions (
message_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
form_id BIGINT NOT NULL,
user_name VARCHAR NOT NULL,
PRIMARY KEY (message_id),
FOREIGN KEY (form_id) REFERENCES FORMS(form_id) ON DELETE CASCADE ON UPDATE RESTRICT
);

CREATE INDEX FORM_SUBMISSIONS_USER_ID_IDX ON form_submissions (user_id,form_id);
43 changes: 43 additions & 0 deletions src/test/java/net/discordjug/javabot/DatabaseTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package net.discordjug.javabot;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.IOException;
import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.sql.SQLException;
import java.util.Set;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import net.discordjug.javabot.data.h2db.DbHelper;
import net.discordjug.javabot.data.h2db.commands.MigrateSubcommand;
import net.dv8tion.jda.api.interactions.commands.Command.Choice;
import org.h2.jdbcx.JdbcDataSource;
import org.junit.jupiter.api.Test;

public class DatabaseTest {
@Test
void testCreateDatabaseFromSchema() throws SQLException, IOException {
JdbcDataSource ds = new JdbcDataSource();
ds.setUrl("jdbc:h2:mem:"+UUID.randomUUID().toString());
DbHelper.initializeSchema(ds);
}

@Test
void testDatabaseFilesCorrect() throws URISyntaxException, IOException {
Set<String> expectedMigrations;
try (Stream<Path> list = Files.list(Path.of("src/main/resources/database/migrations"))) {
expectedMigrations = list
.map(path -> path.getFileName().toString())
.filter(file -> file.endsWith(".sql"))
.collect(Collectors.toSet());
}
Set<String> foundMigrations = MigrateSubcommand.getAvailableMigrations().stream()
.map(Choice::getName)
.collect(Collectors.toSet());
assertEquals(expectedMigrations, foundMigrations);
}
}