migrations work
This commit is contained in:
parent
2fa76d84df
commit
9ab8902dd6
17
.idea/dataSources.xml
generated
Normal file
17
.idea/dataSources.xml
generated
Normal file
@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||
<data-source source="LOCAL" name="bolts@localhost" uuid="0c3816cc-be27-438f-91ac-28ac37a4af01">
|
||||
<driver-ref>mariadb</driver-ref>
|
||||
<synchronize>true</synchronize>
|
||||
<jdbc-driver>org.mariadb.jdbc.Driver</jdbc-driver>
|
||||
<jdbc-url>jdbc:mariadb://localhost:3306/bolts</jdbc-url>
|
||||
<jdbc-additional-properties>
|
||||
<property name="com.intellij.clouds.kubernetes.db.host.port" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
|
||||
<property name="com.intellij.clouds.kubernetes.db.container.port" />
|
||||
</jdbc-additional-properties>
|
||||
<working-dir>$ProjectFileDir$</working-dir>
|
||||
</data-source>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/data_source_mapping.xml
generated
Normal file
6
.idea/data_source_mapping.xml
generated
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DataSourcePerFileMappings">
|
||||
<file url="file://$APPLICATION_CONFIG_DIR$/consoles/db/0c3816cc-be27-438f-91ac-28ac37a4af01/console.sql" value="0c3816cc-be27-438f-91ac-28ac37a4af01" />
|
||||
</component>
|
||||
</project>
|
||||
4
.idea/kotlinc.xml
generated
4
.idea/kotlinc.xml
generated
@ -7,8 +7,8 @@
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
</component>
|
||||
<component name="KotlinCommonCompilerArguments">
|
||||
<option name="apiVersion" value="2.1" />
|
||||
<option name="languageVersion" value="2.1" />
|
||||
<option name="apiVersion" value="2.2" />
|
||||
<option name="languageVersion" value="2.2" />
|
||||
</component>
|
||||
<component name="KotlinJpsPluginSettings">
|
||||
<option name="version" value="2.2.0" />
|
||||
|
||||
15
pom.xml
15
pom.xml
@ -134,15 +134,18 @@
|
||||
<version>2.0.16</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-scripting-jvm</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
<version>2.20.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-scripting-common</artifactId>
|
||||
<version>${kotlin.version}</version>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>3.18.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- TEST -->
|
||||
|
||||
@ -4,16 +4,25 @@ import io.javalin.Javalin;
|
||||
import org.apache.commons.dbutils.DbUtils;
|
||||
import org.apache.commons.dbutils.QueryRunner;
|
||||
import org.apache.commons.dbutils.handlers.ScalarHandler;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
|
||||
/** Hello world! */
|
||||
public class App {
|
||||
public static void main(String[] args) {
|
||||
System.setProperty("org.jooq.no-tips", "true");
|
||||
System.setProperty("org.jooq.no-logo", "true");
|
||||
|
||||
Db db =
|
||||
Db.Builder.create()
|
||||
.url("jdbc:mariadb://localhost:3306/bolts")
|
||||
@ -22,7 +31,22 @@ public class App {
|
||||
.build();
|
||||
|
||||
db.init();
|
||||
Migration.of(db).getPendingBaseMigrations().forEach(f -> System.out.println(f.getName()));
|
||||
List<File> pendingBaseMigrations = Migration.of(db).getPendingBaseMigrations();
|
||||
for (File file : pendingBaseMigrations) {
|
||||
LoggerFactory.getLogger(App.class).info("Running migration: {}", file.getName());
|
||||
try (Connection connection = db.getConnection()) {
|
||||
String content = FileUtils.readFileToString(file, StandardCharsets.UTF_8);
|
||||
db.run(connection, content);
|
||||
DSL.using(connection)
|
||||
.insertInto(DSL.table("_migrations"))
|
||||
.columns(DSL.field("name"), DSL.field("base"), DSL.field("executedAt"))
|
||||
.values(
|
||||
file.getName(), true, LocalDateTime.now()) // executedAt is null for base migrations
|
||||
.execute();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
var app = Javalin.create(cnf -> {});
|
||||
app.before(
|
||||
|
||||
@ -84,13 +84,18 @@ public class Db {
|
||||
|
||||
public void run(String query) {
|
||||
try (Connection connection = getConnection()) {
|
||||
dsl.execute(query);
|
||||
connection.commit();
|
||||
run(connection, query);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
public DSLContext dsl() {
|
||||
return dsl;
|
||||
|
||||
public void run(Connection connection, String query) {
|
||||
try {
|
||||
DSL.using(connection).execute(query);
|
||||
connection.commit();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,20 +1,14 @@
|
||||
package dev.mduchene;
|
||||
|
||||
import org.jooq.Meta;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.sql.Connection;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
import org.jooq.Meta;
|
||||
import org.jooq.Record1;
|
||||
import org.jooq.SelectConditionStep;
|
||||
import org.jooq.impl.DSL;
|
||||
|
||||
public class Migration {
|
||||
|
||||
@ -38,14 +32,19 @@ public class Migration {
|
||||
|
||||
public boolean tableExists(String tableName) {
|
||||
// Get the Meta object, which contains all database metadata
|
||||
Meta meta = db.dsl().meta();
|
||||
try {
|
||||
Connection connection = db.getConnection();
|
||||
Meta meta = DSL.using(connection).meta();
|
||||
|
||||
// Use the getTables() method with a filter
|
||||
return meta.getTables(DSL.name("bolts", tableName)).stream()
|
||||
.anyMatch(
|
||||
table ->
|
||||
table.getName().equalsIgnoreCase(tableName)
|
||||
&& table.getSchema().getName().equalsIgnoreCase("bolts"));
|
||||
// Use the getTables() method with a filter
|
||||
return meta.getTables(DSL.name("bolts", tableName)).stream()
|
||||
.anyMatch(
|
||||
table ->
|
||||
table.getName().equalsIgnoreCase(tableName)
|
||||
&& table.getSchema().getName().equalsIgnoreCase("bolts"));
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public List<String> getRanBaseMigrations() {
|
||||
@ -53,11 +52,10 @@ public class Migration {
|
||||
boolean migrationsExists = tableExists("_migrations");
|
||||
if (!migrationsExists) return List.of();
|
||||
|
||||
return db.dsl()
|
||||
return DSL.using(connection)
|
||||
.select(DSL.field("name"))
|
||||
.from(DSL.table("_migrations"))
|
||||
.where(DSL.field("base").eq(true))
|
||||
.and(DSL.field("executedAt").isNull())
|
||||
.fetch(DSL.field("name"), String.class);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
@ -66,7 +64,7 @@ public class Migration {
|
||||
|
||||
public List<String> getRanMigrations() {
|
||||
try (Connection connection = db.getConnection()) {
|
||||
return db.dsl()
|
||||
return DSL.using(connection)
|
||||
.select(DSL.field("name"))
|
||||
.from(DSL.table("_migrations"))
|
||||
.fetch(DSL.field("name"), String.class);
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
create table _migrations (
|
||||
name varchar(255) primary key,
|
||||
executedAt timestamp,
|
||||
base int(1),
|
||||
content longtext
|
||||
)
|
||||
96
src/test/java/dev/mduchene/MigrationTest.java
Normal file
96
src/test/java/dev/mduchene/MigrationTest.java
Normal file
@ -0,0 +1,96 @@
|
||||
|
||||
package dev.mduchene;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class MigrationTest {
|
||||
|
||||
// private Db db;
|
||||
// private Migration migration;
|
||||
//
|
||||
// @BeforeEach
|
||||
// public void setUp() {
|
||||
// db = Db.Builder.create()
|
||||
// .url("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MySQL")
|
||||
// .user("sa")
|
||||
// .password("")
|
||||
// .build();
|
||||
// db.init();
|
||||
// migration = Migration.of(db);
|
||||
// }
|
||||
//
|
||||
// @AfterEach
|
||||
// public void tearDown() throws IOException {
|
||||
// // Clean up the created migration files
|
||||
// File migrationsDir = new File("src/main/resources/migrations");
|
||||
// for (File file : Objects.requireNonNull(migrationsDir.listFiles())) {
|
||||
// if (!file.getName().equals(".gitkeep")) {
|
||||
// Files.delete(file.toPath());
|
||||
// }
|
||||
// }
|
||||
// db.run("DROP ALL OBJECTS");
|
||||
// }
|
||||
//
|
||||
//
|
||||
//
|
||||
// @Test
|
||||
// public void testCreateMigration() {
|
||||
// migration.create("test_migration");
|
||||
// File migrationsDir = new File("src/main/resources/migrations");
|
||||
// assertEquals(1, Objects.requireNonNull(migrationsDir.listFiles()).length);
|
||||
// assertTrue(Objects.requireNonNull(migrationsDir.listFiles())[0].getName().contains("_test_migration.sql"));
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testGetPendingMigrations() throws IOException {
|
||||
// // Create a dummy migration file
|
||||
// Path newFile = Paths.get("src/main/resources/migrations/20230101000000_initial.sql");
|
||||
// Files.createFile(newFile);
|
||||
//
|
||||
// List<String> pending = migration.getPending();
|
||||
// assertEquals(1, pending.size());
|
||||
// assertEquals("20230101000000_initial.sql", pending.get(0));
|
||||
//
|
||||
// // Run the migration
|
||||
// db.run("INSERT INTO _migrations (name) VALUES ('20230101000000_initial.sql')");
|
||||
//
|
||||
// pending = migration.getPending();
|
||||
// assertEquals(0, pending.size());
|
||||
// }
|
||||
//
|
||||
// @Test
|
||||
// public void testRunMigrations() throws IOException {
|
||||
// // Create a dummy migration file with some SQL
|
||||
// String migrationName = "20230101000001_create_users_table.sql";
|
||||
// Path newFile = Paths.get("src/main/resources/migrations/" + migrationName);
|
||||
// Files.write(newFile, "CREATE TABLE users (id INT PRIMARY KEY, name VARCHAR(255));".getBytes());
|
||||
//
|
||||
// // Run pending migrations
|
||||
// List<String> pending = migration.getPending();
|
||||
// migration.run(pending);
|
||||
//
|
||||
// // Check if the table was created
|
||||
// try {
|
||||
// db.run("SELECT * FROM users");
|
||||
// } catch (Exception e) {
|
||||
// fail("Table 'users' should have been created by the migration.");
|
||||
// }
|
||||
//
|
||||
// // Check if the migration was recorded in the _migrations table
|
||||
//// List<String> ranMigrations = db.getRanMigrations();
|
||||
//// assertEquals(1, ranMigrations.size());
|
||||
//// assertEquals(migrationName, ranMigrations.get(0));
|
||||
// }
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user