diff --git a/pom.xml b/pom.xml index 2751842..abe5659 100644 --- a/pom.xml +++ b/pom.xml @@ -24,8 +24,8 @@ maven-compiler-plugin 3.13.0 - ${java.version} - ${java.version} + 21 + 21 diff --git a/src/main/java/fr/molzonas/mzcore/database/MZCodegen.java b/src/main/java/fr/molzonas/mzcore/database/MZCodegen.java index df98948..0bfa283 100644 --- a/src/main/java/fr/molzonas/mzcore/database/MZCodegen.java +++ b/src/main/java/fr/molzonas/mzcore/database/MZCodegen.java @@ -1,5 +1,162 @@ package fr.molzonas.mzcore.database; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import fr.molzonas.mzcore.database.provider.MZDatabaseProvider; +import fr.molzonas.mzcore.database.provider.MZDatabaseProviderMariaDB; +import fr.molzonas.mzcore.database.provider.MZDatabaseProviderPostgreSQL; +import fr.molzonas.mzcore.database.provider.MZDatabaseProviderSQLite; +import org.flywaydb.core.Flyway; +import org.jooq.SQLDialect; +import org.jooq.codegen.GenerationTool; +import org.jooq.meta.jaxb.*; + +import java.util.Locale; + public final class MZCodegen { - // TODO -} + private MZCodegen() {} + + public static void migrate(MZDatabaseConfiguration config) { + MZDatabaseProvider provider = chooseProvider(config); + try (HikariDataSource dataSource = buildDataSource(config, provider)) { + Flyway.configure() + .dataSource(dataSource) + .locations(provider.migrationLocation()) + .baselineOnMigrate(true) + .cleanDisabled(true) + .load() + .migrate(); + } + } + + public static void generate(MZDatabaseConfiguration config, + String targetFolder, + String targetPackage) { + MZDatabaseProvider provider = chooseProvider(config); + try { + GenerationTool.generate(buildJooqConfiguration(config, provider, targetFolder, targetPackage)); + } catch (Exception e) { + throw new RuntimeException("jOOQ codegen failed", e); + } + } + + private static MZDatabaseProvider chooseProvider(MZDatabaseConfiguration config) { + return switch (config.getType().trim().toUpperCase(Locale.ROOT)) { + case "MARIADB", "MYSQL" -> new MZDatabaseProviderMariaDB(); + case "POSTGRES", "POSTGRESQL" -> new MZDatabaseProviderPostgreSQL(); + default -> new MZDatabaseProviderSQLite(); + }; + } + + private static HikariDataSource buildDataSource(MZDatabaseConfiguration config, MZDatabaseProvider provider) { + HikariConfig hc = new HikariConfig(); + hc.setJdbcUrl(provider.jdbcUrl(config)); + if (!config.isSQLite()) { + hc.setUsername(config.getUsername()); + hc.setPassword(config.getPassword()); + } + hc.setMaximumPoolSize(config.getMaximumPoolSize()); + hc.setMinimumIdle(config.getMinimumIdle()); + hc.setConnectionTimeout(config.getConnectionTimeout()); + hc.setIdleTimeout(config.getIdleTimeout()); + hc.setMaxLifetime(config.getMaximumLifetime()); + hc.setPoolName("MZ-Codegen-" + config.getType()); + provider.tune(hc, config); + return new HikariDataSource(hc); + } + + private static Configuration buildJooqConfiguration(MZDatabaseConfiguration config, + MZDatabaseProvider provider, + String targetFolder, + String targetPackage) { + String metaDbName = metaDatabaseName(provider.dialect()); + String inputSchema = defaultInputSchema(provider.dialect(), config); + Database db = new Database() + .withName(metaDbName) + .withIncludes(".*") + .withExcludes("(?i)flyway_schema_history") + .withInputSchema(inputSchema); + Generator generator = new Generator() + .withDatabase(db) + .withTarget(new Target() + .withDirectory(targetFolder) + .withPackageName(targetPackage)) + .withGenerate(new Generate() + .withPojos(true) + .withDaos(false) + .withFluentSetters(true) + .withRecords(true) + .withJavaTimeTypes(true)); + + Jdbc jdbc = new Jdbc() + .withUrl(provider.jdbcUrl(config)) + .withUser(config.isSQLite() ? null : config.getUsername()) + .withPassword(config.isSQLite() ? null : config.getPassword()) + .withDriver(jdbcDriverName(provider.dialect())); + + return new Configuration() + .withJdbc(jdbc) + .withGenerator(generator); + } + + private static String metaDatabaseName(SQLDialect dialect) { + return switch (dialect.family()) { + case MARIADB, MYSQL -> "org.jooq.meta.mariadb.MariaDBDatabase"; + case POSTGRES -> "org.jooq.meta.postgres.PostgresDatabase"; + default -> "org.jooq.meta.sqlite.SQLiteDatabase"; + }; + } + + private static String jdbcDriverName(SQLDialect dialect) { + return switch (dialect.family()) { + case MARIADB, MYSQL -> "org.mariadb.jdbc.Driver"; + case POSTGRES -> "org.postgresql.Driver"; + default -> "org.sqlite.JDBC"; + }; + } + + private static String defaultInputSchema(SQLDialect dialect, MZDatabaseConfiguration config) { + return switch (dialect.family()) { + case MARIADB, MYSQL -> config.getDatabase(); + case POSTGRES -> "public"; + default -> null; + }; + } + + /* + * Example codegen + * public static void main(String[] args) { + * long t1 = System.currentTimeMillis(); + * String type = System.getProperty("db.type", "sqlite"); + * String host = System.getProperty("db.host", "127.0.0.1"); + * int port = Integer.parseInt(System.getProperty("db.port", + * switch (type.toLowerCase(Locale.ROOT)) { + * case "postgres", "postgresql" -> "5432"; + * case "mariadb", "mysql" -> "3306"; + * default -> "0"; + * })); + * String name = System.getProperty("db.name", "myplugin"); + * String user = System.getProperty("db.user", ""); + * String pass = System.getProperty("db.pass", ""); + * boolean ssl = Boolean.parseBoolean(System.getProperty("db.ssl", "false")); + * String sslMode = System.getProperty("db.sslmode", ""); + * String pkg = System.getProperty("jooq.pkg", "fr.molzonas.example.database.generated"); + * String out = System.getProperty("jooq.out", "target/generated-sources/jooq"); + * + * var config = MZDatabaseConfiguration.builder() + * .setType(type) + * .setHost(host) + * .setPort(port) + * .setDatabase(name) + * .setUsername(user) + * .setPassword(pass) + * .setSslEnabled(ssl) + * .setSslMode(sslMode) + * .build(); + * + * migrate(config); + * generate(config, out, pkg); + * System.out.println("Codegen ended in " + (System.currentTimeMillis() - t1) + "ms"); + * } + */ +} \ No newline at end of file diff --git a/src/main/java/fr/molzonas/mzcore/database/MZDatabaseConfiguration.java b/src/main/java/fr/molzonas/mzcore/database/MZDatabaseConfiguration.java index 2948fd8..069d92c 100644 --- a/src/main/java/fr/molzonas/mzcore/database/MZDatabaseConfiguration.java +++ b/src/main/java/fr/molzonas/mzcore/database/MZDatabaseConfiguration.java @@ -1,5 +1,6 @@ package fr.molzonas.mzcore.database; +import fr.molzonas.mzcore.MZConfig; import lombok.Getter; public class MZDatabaseConfiguration { @@ -46,6 +47,30 @@ public class MZDatabaseConfiguration { public boolean isPostgreSQL() { return "postgresql".equalsIgnoreCase(type); } + + public static MZDatabaseConfiguration getDefault() { + return new MZDatabaseConfiguration(); + } + + public static MZDatabaseConfiguration getFromConfiguration(MZConfig config) { + MZDatabaseConfiguration.Builder builder = MZDatabaseConfiguration.builder(); + if (config.exists("database.type")) builder.setType(config.get("database.type")); + if (config.exists("database.host")) builder.setHost(config.get("database.host")); + if (config.exists("database.port")) builder.setPort(config.get("database.port", Integer.class)); + if (config.exists("database.database")) builder.setDatabase(config.get("database.database")); + if (config.exists("database.username")) builder.setUsername(config.get("database.username")); + if (config.exists("database.password")) builder.setPassword(config.get("database.password")); + if (config.exists("database.file")) builder.setFile(config.get("database.file")); + if (config.exists("database.maximumPoolSize")) builder.setMaximumPoolSize(config.get("database.maximumPoolSize", Integer.class)); + if (config.exists("database.minimumIdle")) builder.setMinimumIdle(config.get("database.minimumIdle", Integer.class)); + if (config.exists("database.maximumLifetime")) builder.setMaximumLifetime(config.get("database.maximumLifetime", Integer.class)); + if (config.exists("database.connectionTimeout")) builder.setConnectionTimeout(config.get("database.connectionTimeout", Integer.class)); + if (config.exists("database.idleTimeout")) builder.setIdleTimeout(config.get("database.idleTimeout", Integer.class)); + if (config.exists("database.sslEnabled")) builder.setSslEnabled(config.get("database.sslEnabled", Boolean.class)); + if (config.exists("database.sslMode")) builder.setSslMode(config.get("database.sslMode")); + return builder.build(); + } + public static class Builder { final MZDatabaseConfiguration mzDatabaseConfiguration; public Builder() {