Dieser Commit ist enthalten in:
Lixfel 2022-11-02 22:38:21 +01:00
Ursprung 92bea6255f
Commit bd626bb4e6
9 geänderte Dateien mit 59 neuen und 30 gelöschten Zeilen

Datei anzeigen

@ -24,7 +24,6 @@ import de.steamwar.sql.internal.SelectStatement;
import de.steamwar.sql.internal.Statement; import de.steamwar.sql.internal.Statement;
import de.steamwar.sql.internal.Table; import de.steamwar.sql.internal.Table;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
@ -32,6 +31,10 @@ import java.util.Set;
@AllArgsConstructor @AllArgsConstructor
public class NodeMember { public class NodeMember {
public static void init() {
// enforce class initialization
}
private static final Table<NodeMember> table = new Table<>(NodeMember.class); private static final Table<NodeMember> table = new Table<>(NodeMember.class);
private static final SelectStatement<NodeMember> getNodeMember = table.select(Table.PRIMARY); private static final SelectStatement<NodeMember> getNodeMember = table.select(Table.PRIMARY);
private static final SelectStatement<NodeMember> getNodeMembers = table.selectFields("Node"); private static final SelectStatement<NodeMember> getNodeMembers = table.selectFields("Node");
@ -39,15 +42,21 @@ public class NodeMember {
private static final Statement create = table.insertAll(); private static final Statement create = table.insertAll();
private static final Statement delete = table.delete(Table.PRIMARY); private static final Statement delete = table.delete(Table.PRIMARY);
@Getter
@Field(keys = {Table.PRIMARY}) @Field(keys = {Table.PRIMARY})
private final int node; private final int nodeId;
@Getter
@Field(keys = {Table.PRIMARY}) @Field(keys = {Table.PRIMARY})
private final int member; private final int userId;
public int getNodeId() {
return nodeId;
}
public int getUserId() {
return userId;
}
public void delete() { public void delete() {
delete.update(node, member); delete.update(nodeId, userId);
} }
public static NodeMember createNodeMember(int node, int member) { public static NodeMember createNodeMember(int node, int member) {

Datei anzeigen

@ -28,6 +28,7 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.sql.SQLException; import java.sql.SQLException;
@AllArgsConstructor @AllArgsConstructor
@ -36,9 +37,9 @@ public class Replay {
static { static {
new SqlTypeMapper<>(File.class, "BLOB", (rs, identifier) -> { new SqlTypeMapper<>(File.class, "BLOB", (rs, identifier) -> {
try { try {
File file = File.createTempFile("replay", "replay"); File file = File.createTempFile("replay", ".replay");
file.deleteOnExit(); file.deleteOnExit();
Files.copy(rs.getBinaryStream(identifier), file.toPath()); Files.copy(rs.getBinaryStream(identifier), file.toPath(), StandardCopyOption.REPLACE_EXISTING);
return file; return file;
} catch (IOException e) { } catch (IOException e) {
throw new SQLException(e); throw new SQLException(e);

Datei anzeigen

@ -40,7 +40,7 @@ public class SWException {
private static final Table<SWException> table = new Table<>(SWException.class, "Exception"); private static final Table<SWException> table = new Table<>(SWException.class, "Exception");
private static final Statement insert = table.insertFields("server", "message", "stacktrace"); private static final Statement insert = table.insertFields("server", "message", "stacktrace");
@Field(keys = {Table.PRIMARY}) @Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int id; private final int id;
@Field(def = "CURRENT_TIMESTAMP") @Field(def = "CURRENT_TIMESTAMP")
private final Timestamp time; private final Timestamp time;

Datei anzeigen

@ -72,6 +72,10 @@ public class SchematicNode {
private static final SelectStatement<SchematicNode> allAccessibleByUser = new SelectStatement<>(table, "WITH RECURSIVE RSN as (" + nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId UNION " + nodeSelectCreator("SN.") + "AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN ORDER BY NodeName"); private static final SelectStatement<SchematicNode> allAccessibleByUser = new SelectStatement<>(table, "WITH RECURSIVE RSN as (" + nodeSelectCreator("s.") + "s LEFT JOIN NodeMember n ON s.NodeId = n.NodeId WHERE (s.NodeOwner = ? OR n.UserId = ?) GROUP BY s.NodeId UNION " + nodeSelectCreator("SN.") + "AS SN, RSN WHERE SN.ParentNode = RSN.NodeId) SELECT * FROM RSN ORDER BY NodeName");
private static final SelectStatement<SchematicNode> allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (" + nodeSelectCreator("") + "WHERE NodeId = ? UNION " + nodeSelectCreator("SN.") + "SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT * FROM RSN ORDER BY NodeName"); private static final SelectStatement<SchematicNode> allParentsOfNode = new SelectStatement<>(table, "WITH RECURSIVE RSN AS (" + nodeSelectCreator("") + "WHERE NodeId = ? UNION " + nodeSelectCreator("SN.") + "SN, RSN WHERE RSN.ParentNode = SN.NodeId) SELECT * FROM RSN ORDER BY NodeName");
static {
NodeMember.init();
}
@Field(keys = {Table.PRIMARY}, autoincrement = true) @Field(keys = {Table.PRIMARY}, autoincrement = true)
private final int nodeId; private final int nodeId;
@Field(keys = {"OwnerNameParent"}) @Field(keys = {"OwnerNameParent"})
@ -476,7 +480,7 @@ public class SchematicNode {
final Set<NodeMember> nodeMembers = NodeMember.getSchematics(user.getId()); final Set<NodeMember> nodeMembers = NodeMember.getSchematics(user.getId());
AtomicInteger i = new AtomicInteger(); AtomicInteger i = new AtomicInteger();
i.set(currentNode.getId()); i.set(currentNode.getId());
while (currentNode.getParentNode() != null && nodeMembers.stream().noneMatch(nodeMember -> nodeMember.getNode() == i.get())) { while (currentNode.getParentNode() != null && nodeMembers.stream().noneMatch(nodeMember -> nodeMember.getNodeId() == i.get())) {
currentNode = currentNode.getParentNode(); currentNode = currentNode.getParentNode();
i.set(currentNode.getId()); i.set(currentNode.getId());
builder.insert(0, split) builder.insert(0, split)

Datei anzeigen

@ -101,7 +101,7 @@ public class SteamwarUser {
this.leader = leader; this.leader = leader;
this.locale = locale; this.locale = locale;
this.manualLocale = manualLocale; this.manualLocale = manualLocale;
this.discordId = discordId != 0 ? discordId : null; this.discordId = discordId != null && discordId != 0 ? discordId : null;
usersById.put(id, this); usersById.put(id, this);
usersByName.put(userName.toLowerCase(), this); usersByName.put(userName.toLowerCase(), this);
@ -118,7 +118,16 @@ public class SteamwarUser {
public Locale getLocale() { public Locale getLocale() {
if(locale != null) if(locale != null)
return locale; return locale;
return Locale.getDefault(); //TODO test correct locale on join (z.B. FightSystem Hotbarkit) return Locale.getDefault();
}
public void setLocale(Locale locale, boolean manualLocale) {
if (locale == null || (this.manualLocale && !manualLocale))
return;
this.locale = locale;
this.manualLocale = manualLocale;
updateLocale.update(locale.toLanguageTag(), manualLocale, id);
} }
public static SteamwarUser get(String userName){ public static SteamwarUser get(String userName){

Datei anzeigen

@ -31,7 +31,7 @@ public class SelectStatement<T> extends Statement {
private final Table<T> table; private final Table<T> table;
SelectStatement(Table<T> table, String... kfields) { SelectStatement(Table<T> table, String... kfields) {
this(table, "SELECT " + Arrays.stream(table.fields).map(f -> f.identifier).collect(Collectors.joining(", ")) + " FROM " + table.name + " WHERE " + Arrays.stream(kfields).map(f -> f + " = ?").collect(Collectors.joining(", "))); this(table, "SELECT " + Arrays.stream(table.fields).map(f -> f.identifier).collect(Collectors.joining(", ")) + " FROM " + table.name + " WHERE " + Arrays.stream(kfields).map(f -> f + " = ?").collect(Collectors.joining(" AND ")));
} }
public SelectStatement(Table<T> table, String sql) { public SelectStatement(Table<T> table, String sql) {

Datei anzeigen

@ -47,7 +47,7 @@ public final class SqlTypeMapper<T> {
public static <T extends Enum<T>> void nameEnumMapper(Class<T> type) { public static <T extends Enum<T>> void nameEnumMapper(Class<T> type) {
new SqlTypeMapper<>( new SqlTypeMapper<>(
type, type,
"VARCHAR(" + Arrays.stream(type.getEnumConstants()).map(e -> e.name().length()).max(Integer::compareTo).get() + ")", "VARCHAR(" + Arrays.stream(type.getEnumConstants()).map(e -> e.name().length()).max(Integer::compareTo).orElse(0) + ")",
(rs, identifier) -> Enum.valueOf(type, rs.getString(identifier)), (rs, identifier) -> Enum.valueOf(type, rs.getString(identifier)),
(st, index, value) -> st.setString(index, value.name()) (st, index, value) -> st.setString(index, value.name())
); );
@ -57,7 +57,7 @@ public final class SqlTypeMapper<T> {
primitiveMapper(boolean.class, Boolean.class, "BOOLEAN", ResultSet::getBoolean, PreparedStatement::setBoolean); primitiveMapper(boolean.class, Boolean.class, "BOOLEAN", ResultSet::getBoolean, PreparedStatement::setBoolean);
primitiveMapper(byte.class, Byte.class, "INTEGER(1)", ResultSet::getByte, PreparedStatement::setByte); primitiveMapper(byte.class, Byte.class, "INTEGER(1)", ResultSet::getByte, PreparedStatement::setByte);
primitiveMapper(short.class, Short.class, "INTEGER(2)", ResultSet::getShort, PreparedStatement::setShort); primitiveMapper(short.class, Short.class, "INTEGER(2)", ResultSet::getShort, PreparedStatement::setShort);
primitiveMapper(int.class, Integer.class, "INTEGER(4)", ResultSet::getInt, PreparedStatement::setInt); primitiveMapper(int.class, Integer.class, "INTEGER", ResultSet::getInt, PreparedStatement::setInt);
primitiveMapper(long.class, Long.class, "INTEGER(8)", ResultSet::getLong, PreparedStatement::setLong); primitiveMapper(long.class, Long.class, "INTEGER(8)", ResultSet::getLong, PreparedStatement::setLong);
primitiveMapper(float.class, Float.class, "REAL", ResultSet::getFloat, PreparedStatement::setFloat); primitiveMapper(float.class, Float.class, "REAL", ResultSet::getFloat, PreparedStatement::setFloat);
primitiveMapper(double.class, Double.class, "REAL", ResultSet::getDouble, PreparedStatement::setDouble); primitiveMapper(double.class, Double.class, "REAL", ResultSet::getDouble, PreparedStatement::setDouble);

Datei anzeigen

@ -26,6 +26,7 @@ import java.sql.*;
import java.util.*; import java.util.*;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.function.UnaryOperator;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
@ -38,15 +39,17 @@ public class Statement implements AutoCloseable {
private static final int MAX_CONNECTIONS; private static final int MAX_CONNECTIONS;
private static final Supplier<Connection> conProvider; private static final Supplier<Connection> conProvider;
static final Consumer<Table<?>> schemaCreator; static final Consumer<Table<?>> schemaCreator;
static final String ON_DUPLICATE_KEY;
static final UnaryOperator<String> upsertWrapper;
private static final boolean mysqlMode; private static final boolean MYSQL_MODE;
private static final boolean productionDatabase; private static final boolean PRODUCTION_DATABASE;
static { static {
File file = new File(System.getProperty("user.home"), "mysql.properties"); File file = new File(System.getProperty("user.home"), "mysql.properties");
mysqlMode = file.exists(); MYSQL_MODE = file.exists();
if(mysqlMode) { if(MYSQL_MODE) {
Properties properties = new Properties(); Properties properties = new Properties();
try { try {
properties.load(new FileReader(file)); properties.load(new FileReader(file));
@ -58,7 +61,7 @@ public class Statement implements AutoCloseable {
String user = properties.getProperty("user"); String user = properties.getProperty("user");
String password = properties.getProperty("password"); String password = properties.getProperty("password");
productionDatabase = "core".equals(properties.getProperty("database")); PRODUCTION_DATABASE = "core".equals(properties.getProperty("database"));
MAX_CONNECTIONS = SQLConfig.impl.maxConnections(); MAX_CONNECTIONS = SQLConfig.impl.maxConnections();
conProvider = () -> { conProvider = () -> {
try { try {
@ -68,6 +71,8 @@ public class Statement implements AutoCloseable {
} }
}; };
schemaCreator = table -> {}; schemaCreator = table -> {};
ON_DUPLICATE_KEY = " ON DUPLICATE KEY UPDATE ";
upsertWrapper = f -> f + " = VALUES(" + f + ")";
} else { } else {
Connection connection; Connection connection;
@ -78,10 +83,12 @@ public class Statement implements AutoCloseable {
throw new SecurityException("Could not create sqlite connection", e); throw new SecurityException("Could not create sqlite connection", e);
} }
productionDatabase = false; PRODUCTION_DATABASE = false;
MAX_CONNECTIONS = 1; MAX_CONNECTIONS = 1;
conProvider = () -> connection; conProvider = () -> connection;
schemaCreator = Table::ensureExistanceInSqlite; schemaCreator = Table::ensureExistanceInSqlite;
ON_DUPLICATE_KEY = " ON CONFLICT DO UPDATE SET ";
upsertWrapper = f -> f + " = " + f;
} }
} }
@ -99,11 +106,11 @@ public class Statement implements AutoCloseable {
} }
public static boolean mysqlMode() { public static boolean mysqlMode() {
return mysqlMode; return MYSQL_MODE;
} }
public static boolean productionDatabase() { public static boolean productionDatabase() {
return productionDatabase; return PRODUCTION_DATABASE;
} }
private final boolean returnGeneratedKeys; private final boolean returnGeneratedKeys;

Datei anzeigen

@ -53,7 +53,7 @@ public class Table<T> {
keys = Arrays.stream(fields).flatMap(field -> Arrays.stream(field.field.keys())).distinct().collect(Collectors.toMap(Function.identity(), key -> Arrays.stream(fields).filter(field -> Arrays.asList(field.field.keys()).contains(key)).toArray(TableField[]::new))); keys = Arrays.stream(fields).flatMap(field -> Arrays.stream(field.field.keys())).distinct().collect(Collectors.toMap(Function.identity(), key -> Arrays.stream(fields).filter(field -> Arrays.asList(field.field.keys()).contains(key)).toArray(TableField[]::new)));
for (TableField<?> field : fields) { for (TableField<?> field : fields) {
fieldsByIdentifier.put(field.identifier, field); fieldsByIdentifier.put(field.identifier.toLowerCase(), field);
} }
Statement.schemaCreator.accept(this); Statement.schemaCreator.accept(this);
@ -91,8 +91,8 @@ public class Table<T> {
} }
public Statement insertFields(boolean returnGeneratedKeys, String... fields) { public Statement insertFields(boolean returnGeneratedKeys, String... fields) {
List<String> nonKeyFields = Arrays.stream(fields).filter(f -> fieldsByIdentifier.get(f).field.keys().length == 0).collect(Collectors.toList()); List<String> nonKeyFields = Arrays.stream(fields).filter(f -> fieldsByIdentifier.get(f.toLowerCase()).field.keys().length == 0).collect(Collectors.toList());
return new Statement("INSERT INTO " + name + " (" + String.join(", ", fields) + ") VALUES (" + Arrays.stream(fields).map(f -> "?").collect(Collectors.joining(", ")) + ")" + (nonKeyFields.isEmpty() ? "" : " ON DUPLICATE KEY UPDATE " + nonKeyFields.stream().map(f -> f + " = VALUES(" + f + ")").collect(Collectors.joining(", "))), returnGeneratedKeys); return new Statement("INSERT INTO " + name + " (" + String.join(", ", fields) + ") VALUES (" + Arrays.stream(fields).map(f -> "?").collect(Collectors.joining(", ")) + ")" + (nonKeyFields.isEmpty() ? "" : Statement.ON_DUPLICATE_KEY + nonKeyFields.stream().map(Statement.upsertWrapper).collect(Collectors.joining(", "))), returnGeneratedKeys);
} }
public Statement delete(String name) { public Statement delete(String name) {
@ -104,12 +104,11 @@ public class Table<T> {
} }
void ensureExistanceInSqlite() { void ensureExistanceInSqlite() {
List<TableField<?>> primaryKey = keys.containsKey(PRIMARY) ? Arrays.asList(keys.get(PRIMARY)) : Collections.emptyList();
try (Statement statement = new Statement( try (Statement statement = new Statement(
"CREATE TABLE IF NOT EXISTS " + name + "(" + "CREATE TABLE IF NOT EXISTS " + name + "(" +
Arrays.stream(fields).map(field -> field.identifier + " " + field.mapper.sqlType() + (field.field.nullable() ? " DEFAULT NULL" : " NOT NULL") + (field.field.nullable() || field.field.def().equals("") ? "" : " DEFAULT " + field.field.def()) + (primaryKey.contains(field) ? " PRIMARY KEY" : "")).collect(Collectors.joining(", ")) + Arrays.stream(fields).map(field -> field.identifier + " " + field.mapper.sqlType() + (field.field.nullable() ? " DEFAULT NULL" : " NOT NULL") + (field.field.nullable() || field.field.def().equals("") ? "" : " DEFAULT " + field.field.def())).collect(Collectors.joining(", ")) +
keys.entrySet().stream().filter(entry -> !entry.getKey().equals(PRIMARY)).map(key -> ", UNIQUE (" + Arrays.stream(key.getValue()).map(field -> field.identifier).collect(Collectors.joining(", ")) + ")").collect(Collectors.joining(" ")) + keys.entrySet().stream().map(key -> (key.getKey().equals(PRIMARY) ? ", PRIMARY KEY(" : ", UNIQUE (") + Arrays.stream(key.getValue()).map(field -> field.identifier).collect(Collectors.joining(", ")) + ")").collect(Collectors.joining(" ")) +
") WITHOUT ROWID")) { ")")) {
statement.update(); statement.update();
} }
} }