Skip to content

Commit

Permalink
Automatically load driver
Browse files Browse the repository at this point in the history
  • Loading branch information
Tim203 committed Jun 14, 2024
1 parent 4262164 commit df935f1
Show file tree
Hide file tree
Showing 15 changed files with 107 additions and 123 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ currently examples can be found in the tests of the AP module and the tests of t
- support adding every variable of the entity as parameter
- add `save` which either inserts the entity if it's not present or updates the already existing entity
- implementing MongoDB support
- adding migrations
- and plenty more

# Supported types
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ record GeneratedType(String packageName, TypeSpec database) {}

@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latestSupported();
return SourceVersion.latest();
}

private void writeGeneratedTypes(List<GeneratedType> generatedTypes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public Class<?> databaseClass() {
@Override
protected void addEntities(Collection<EntityInfo> entities, MethodSpec.Builder method) {
method.addException(SQLException.class);
method.addStatement("$T dialect = database.dialect()", SqlDialect.class);
method.addStatement("$T type = database.type()", SqlDialect.class);

method.beginControlFlow("try ($T connection = database.dataSource().getConnection())", Connection.class);
method.beginControlFlow("try ($T statement = connection.createStatement())", Statement.class);
Expand All @@ -73,7 +73,7 @@ private CodeBlock.Builder addEntityQuery(EntityInfo entity) {
}

builder.add(
"\"$L \" + $T.sqlTypeFor($T.class, dialect) ",
"\"$L \" + $T.sqlTypeFor($T.class, type) ",
column.name(),
SqlTypeMappingRegistry.class,
ClassName.bestGuess(column.typeName().toString()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,9 @@
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Properties;
import org.geysermc.databaseutils.sql.SqlDialect;

final class CredentialsFileHandler {
public DatabaseConfig handle(SqlDialect dialect, Path credentialsFile) {
public DatabaseConfig handle(DatabaseWithDialectType dialect, Path credentialsFile) {
DatabaseConfig config = defaultValuesFor(dialect);
if (credentialsFile != null) {
if (Files.exists(credentialsFile)) {
Expand Down Expand Up @@ -75,14 +74,15 @@ private void createConfig(DatabaseConfig defaults, Path toStore) {
}
}

private DatabaseConfig defaultValuesFor(SqlDialect dialect) {
return switch (dialect) {
private DatabaseConfig defaultValuesFor(DatabaseWithDialectType type) {
return switch (type) {
case H2 -> configFor("jdbc:h2:./database", "sa");
case SQL_SERVER -> configFor("jdbc:sqlserver://localhost;encrypt=true;integratedSecurity=true;");
case MYSQL -> configFor("jdbc:mysql://localhost/database");
case ORACLE_DATABASE -> configFor("jdbc:oracle:thin:@//localhost/service");
case POSTGRESQL -> configFor("jdbc:postgresql://localhost/database");
case SQLITE -> configFor("jdbc:sqlite:./database");
case MONGODB -> configFor("mongodb://localhost:27017");
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,27 @@

import java.util.concurrent.ExecutorService;
import org.geysermc.databaseutils.codec.TypeCodecRegistry;
import org.geysermc.databaseutils.sql.SqlDialect;

public record DatabaseContext(
String url,
String username,
String password,
String poolName,
int connectionPoolSize,
SqlDialect dialect,
DatabaseWithDialectType type,
ExecutorService service,
TypeCodecRegistry registry) {

public DatabaseContext {
if (poolName == null || poolName.isEmpty())
throw new IllegalArgumentException("poolName cannot be null or empty");
if (dialect == null) throw new IllegalArgumentException("dialect cannot be null");
if (type == null) throw new IllegalArgumentException("A database type has to be provided");
}

public DatabaseContext(
DatabaseConfig config,
String poolName,
SqlDialect dialect,
DatabaseWithDialectType type,
ExecutorService service,
TypeCodecRegistry registry) {
this(
Expand All @@ -55,7 +55,7 @@ public DatabaseContext(
config.password(),
poolName,
config.connectionPoolSize(),
dialect,
type,
service,
registry);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@
final class DatabaseLoader {
@SuppressWarnings({"unchecked"})
@NonNull StartResult startDatabase(DatabaseContext context) {
var database = DatabaseRegistry.firstPresentDatabase();
var database = DatabaseRegistry.databaseFor(context.type());
if (database == null) {
throw new IllegalStateException("Couldn't find any present database");
throw new IllegalStateException("Couldn't find a database manager for " + context.type());
}

Class<?> databaseImplClass;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,20 @@
*/
package org.geysermc.databaseutils;

import java.util.List;
import java.util.Map;
import java.util.function.Supplier;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.databaseutils.sql.SqlDatabase;
import org.geysermc.databaseutils.sql.SqlDatabasePresent;

final class DatabaseRegistry {
private static final List<Supplier<Database>> TYPES = List.of(SqlDatabase::new);
private static final List<DatabaseTypePresent> TYPE_PRESENT = List.of(new SqlDatabasePresent());
private static final Map<DatabaseType, Supplier<Database>> TYPES = Map.of(DatabaseType.SQL, SqlDatabase::new);

public static Database firstPresentDatabase() {
for (int i = 0; i < TYPE_PRESENT.size(); i++) {
if (TYPE_PRESENT.get(i).isPresent()) {
return TYPES.get(i).get();
}
public static @Nullable Database databaseFor(@NonNull DatabaseWithDialectType type) {
var instanceSupplier = TYPES.get(type.databaseType());
if (instanceSupplier == null) {
return null;
}
return null;
return instanceSupplier.get();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package org.geysermc.databaseutils;

public enum DatabaseType {
SQL,
MONGODB
}

This file was deleted.

18 changes: 9 additions & 9 deletions core/src/main/java/org/geysermc/databaseutils/DatabaseUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.concurrent.Executors;
import org.geysermc.databaseutils.codec.TypeCodec;
import org.geysermc.databaseutils.codec.TypeCodecRegistry;
import org.geysermc.databaseutils.sql.SqlDialect;

public class DatabaseUtils {
private final DatabaseContext context;
Expand Down Expand Up @@ -81,7 +80,8 @@ public static class Builder {
private String password;
private String poolName = "database-utils";
private int connectionPoolSize = 0;
private SqlDialect dialect;

private DatabaseWithDialectType type;

private Path credentialsFile;
private boolean useDefaultCredentials = true;
Expand Down Expand Up @@ -158,12 +158,12 @@ public Builder connectionPoolSize(int connectionPoolSize) {
return this;
}

public SqlDialect dialect() {
return dialect;
public DatabaseWithDialectType type() {
return type;
}

public Builder dialect(SqlDialect dialect) {
this.dialect = dialect;
public Builder type(DatabaseWithDialectType type) {
this.type = type;
return this;
}

Expand Down Expand Up @@ -210,14 +210,14 @@ public DatabaseUtils build() {

var actual = config;
if (credentialsFile != null) {
actual = new CredentialsFileHandler().handle(dialect, credentialsFile);
actual = new CredentialsFileHandler().handle(type, credentialsFile);
} else if (useDefaultCredentials) {
actual = new CredentialsFileHandler().handle(dialect, null);
actual = new CredentialsFileHandler().handle(type, null);
} else if (config == null) {
actual = new DatabaseConfig(uri, username, password, connectionPoolSize);
}

return new DatabaseUtils(new DatabaseContext(actual, poolName, dialect, service, registry));
return new DatabaseUtils(new DatabaseContext(actual, poolName, type, service, registry));
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package org.geysermc.databaseutils;

import java.util.Locale;
import java.util.Objects;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;
import org.geysermc.databaseutils.sql.SqlDialect;

public enum DatabaseWithDialectType {
H2(DatabaseType.SQL, SqlDialect.H2),
SQL_SERVER(DatabaseType.SQL, SqlDialect.SQL_SERVER),
MYSQL(DatabaseType.SQL, SqlDialect.MYSQL),
ORACLE_DATABASE(DatabaseType.SQL, SqlDialect.ORACLE_DATABASE),
POSTGRESQL(DatabaseType.SQL, SqlDialect.POSTGRESQL),
SQLITE(DatabaseType.SQL, SqlDialect.SQLITE),
MONGODB(DatabaseType.MONGODB, null);

private static final DatabaseWithDialectType[] VALUES = values();

private final DatabaseType databaseType;
private final SqlDialect dialect;

DatabaseWithDialectType(@NonNull DatabaseType databaseType, @Nullable SqlDialect dialect) {
this.databaseType = Objects.requireNonNull(databaseType);
this.dialect = dialect;
}

public static @Nullable DatabaseWithDialectType byName(@NonNull String name) {
var normalized = name.replace('-', '_').replace(' ', '_').toUpperCase(Locale.ROOT);
for (DatabaseWithDialectType value : VALUES) {
if (value.name().equals(normalized)) {
return value;
}
}
return null;
}

public @NonNull DatabaseType databaseType() {
return databaseType;
}

public @Nullable SqlDialect dialect() {
return dialect;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.zaxxer.hikari.HikariDataSource;
import org.geysermc.databaseutils.Database;
import org.geysermc.databaseutils.DatabaseContext;
import org.geysermc.databaseutils.util.ClassUtils;

public final class SqlDatabase extends Database {
private SqlDialect dialect;
Expand All @@ -36,7 +37,16 @@ public final class SqlDatabase extends Database {
@Override
public void start(DatabaseContext context) {
super.start(context);
this.dialect = context.dialect();
this.dialect = context.type().dialect();

if (dialect == null) {
throw new IllegalStateException("The selected type '" + context.type() + "' is not a sql type");
}

// This also loads the driver
if (!ClassUtils.isClassPresent(dialect.driverName())) {
throw new IllegalStateException("The driver for the selected dialect '" + dialect + "' is not present!");
}

var hikariConfig = new HikariConfig();
hikariConfig.setJdbcUrl(context.url());
Expand Down

This file was deleted.

34 changes: 11 additions & 23 deletions core/src/main/java/org/geysermc/databaseutils/sql/SqlDialect.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,33 +24,21 @@
*/
package org.geysermc.databaseutils.sql;

import java.util.Locale;

public enum SqlDialect {
H2,
SQL_SERVER,
MYSQL,
ORACLE_DATABASE,
POSTGRESQL,
SQLITE;
H2("org.h2.Driver"),
SQL_SERVER("com.microsoft.sqlserver.jdbc.SQLServerDriver"),
MYSQL("org.mariadb.jdbc.Driver"),
ORACLE_DATABASE("oracle.jdbc.driver.OracleDriver"),
POSTGRESQL("org.postgresql.Driver"),
SQLITE("org.sqlite.JDBC"),;

private static final SqlDialect[] VALUES = values();
private final String driverName;

public static SqlDialect byName(String dialectName) {
var normalized = dialectName.replace('-', '_').replace(' ', '_').toUpperCase(Locale.ROOT);
for (SqlDialect value : VALUES) {
if (value.name().equals(normalized)) {
return value;
}
}
return null;
SqlDialect(String driverName) {
this.driverName = driverName;
}

public static SqlDialect requireByName(String dialectName) {
var result = byName(dialectName);
if (result == null) {
throw new IllegalStateException("Could not find dialect for " + dialectName);
}
return result;
public String driverName() {
return driverName;
}
}
Loading

0 comments on commit df935f1

Please sign in to comment.