diff --git a/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt
index 63d8ccaf..fd9a2446 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/NodeData.kt
@@ -17,121 +17,83 @@
* along with this program. If not, see .
*/
-package de.steamwar.sql;
+package de.steamwar.sql
-import de.steamwar.sql.internal.*;
-import lombok.AllArgsConstructor;
-import lombok.Getter;
+import de.steamwar.sql.internal.useDb
+import org.jetbrains.exposed.v1.core.SortOrder
+import org.jetbrains.exposed.v1.core.dao.id.CompositeID
+import org.jetbrains.exposed.v1.core.dao.id.CompositeIdTable
+import org.jetbrains.exposed.v1.core.dao.id.EntityID
+import org.jetbrains.exposed.v1.core.eq
+import org.jetbrains.exposed.v1.core.statements.api.ExposedBlob
+import org.jetbrains.exposed.v1.dao.CompositeEntity
+import org.jetbrains.exposed.v1.dao.CompositeEntityClass
+import org.jetbrains.exposed.v1.javatime.timestamp
+import org.jetbrains.exposed.v1.jdbc.insertIgnore
+import java.io.InputStream
+import java.util.zip.GZIPInputStream
-import javax.swing.plaf.nimbus.State;
-import java.io.*;
-import java.sql.PreparedStatement;
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.util.List;
-import java.util.Optional;
-import java.util.zip.GZIPInputStream;
+object NodeDataTable: CompositeIdTable("NodeData") {
+ val nodeId = reference("NodeId", SchematicNodeTable)
+ val createdAt = timestamp("CreatedAt").entityId()
+ val nodeFormat = enumeration("NodeFormat", NodeData.SchematicFormat::class)
+ val schemData = blob("SchemData")
-@AllArgsConstructor
-@Getter
-public class NodeData {
- static {
- new SqlTypeMapper<>(PipedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("PipedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
- new SqlTypeMapper<>(ByteArrayInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("ByteArrayInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
- new SqlTypeMapper<>(BufferedInputStream.class, "BLOB", (rs, identifier) -> { throw new SecurityException("BufferedInputStream is write only datatype"); }, PreparedStatement::setBinaryStream);
+ override val primaryKey = PrimaryKey(nodeId, createdAt)
- SqlTypeMapper.ordinalEnumMapper(SchematicFormat.class);
+ init {
+ addIdColumn(nodeId)
}
+}
- private static final Table table = new Table<>(NodeData.class);
+class NodeData(id: EntityID): CompositeEntity(id) {
+ val nodeId by NodeDataTable.nodeId
+ val createdAt by NodeDataTable.createdAt
+ val nodeFormat by NodeDataTable.nodeFormat
+ val schemData by NodeDataTable.schemData
- private static final Statement updateDatabase = new Statement("INSERT INTO NodeData(NodeId, NodeFormat, SchemData) VALUES (?, ?, ?)", true);
- private static final Statement selSchemData = new Statement("SELECT SchemData FROM NodeData WHERE NodeId = ? AND CreatedAt = ?");
- private static final Statement delete = table.delete(Table.PRIMARY);
+ companion object: CompositeEntityClass(NodeDataTable) {
+ @JvmStatic
+ fun getLatest(node: SchematicNode) = useDb {
+ find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.DESC).firstOrNull()
+ }
- private static final SelectStatement get = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt ");
- private static final Statement getRevisions = new Statement("SELECT COUNT(DISTINCT CreatedAt) as CNT FROM NodeData WHERE NodeId = ?");
- private static final SelectStatement getLatest = new SelectStatement<>(table, "SELECT NodeId, CreatedAt, NodeFormat FROM NodeData WHERE NodeId = ? ORDER BY CreatedAt DESC LIMIT 1");
+ @JvmStatic
+ fun get(node: SchematicNode) = useDb {
+ find { (NodeDataTable.nodeId eq node.nodeId) }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList()
+ }
- public static NodeData getLatest(SchematicNode node) {
- if (node.isDir()) throw new IllegalArgumentException("Node is dir");
- return Optional.ofNullable(getLatest.select(node)).orElseGet(() -> new NodeData(node.getId(), Timestamp.from(Instant.now()), SchematicFormat.MCEDIT));
- }
+ @JvmStatic
+ fun get(node: SchematicNode, revision: Int) = useDb {
+ find { NodeDataTable.nodeId eq node.nodeId }.orderBy(NodeDataTable.createdAt to SortOrder.ASC).toList().get(revision - 1)
+ }
- public static List get(SchematicNode node) {
- return get.listSelect(node);
- }
+ @JvmStatic
+ fun getRevisions(node: SchematicNode) = useDb {
+ count(NodeDataTable.nodeId eq node.nodeId).toInt()
+ }
- public static NodeData get(SchematicNode node, int revision) {
- return get.listSelect(node).get(revision - 1);
- }
-
- public static int getRevisions(SchematicNode node) {
- return getRevisions.select(rs -> {
- if (rs.next()) {
- return rs.getInt("CNT");
- } else {
- return 0;
+ @JvmStatic
+ fun saveFromStream(node: SchematicNode, blob: InputStream, format: SchematicFormat) {
+ NodeDataTable.insertIgnore {
+ it[NodeDataTable.nodeId] = EntityID(node.getId(), SchematicNodeTable)
+ it[NodeDataTable.nodeFormat] = format
+ it[NodeDataTable.schemData] = ExposedBlob(blob)
}
- }, node);
- }
-
- public static void saveFromStream(SchematicNode node, InputStream blob, SchematicFormat format) {
- updateDatabase.update(node.getId(), format, blob);
- }
-
- @Field(keys = {Table.PRIMARY})
- private final int nodeId;
-
- @Field(keys = {Table.PRIMARY})
- private Timestamp createdAt;
-
- @Field
- public SchematicFormat nodeFormat;
-
- public InputStream schemData() throws IOException {
- return schemData(true);
- }
-
- public InputStream schemData(boolean decompress) throws IOException {
- try {
- return selSchemData.select(rs -> {
- rs.next();
- InputStream schemData = rs.getBinaryStream("SchemData");
- try {
- if(rs.wasNull() || schemData.available() == 0) {
- throw new SecurityException("SchemData is null");
- }
- if (decompress) {
- return new GZIPInputStream(schemData);
- } else {
- return schemData;
- }
- } catch (IOException e) {
- throw new SecurityException("SchemData is wrong", e);
- }
- }, nodeId, createdAt);
- } catch (Exception e) {
- throw new IOException(e);
}
}
- @Deprecated
- public void saveFromStream(InputStream blob, SchematicFormat newFormat) {
- saveFromStream(SchematicNode.getSchematicNode(nodeId), blob, newFormat);
+ fun schemData(decompress: Boolean) = useDb {
+ schemData.inputStream.let { if(decompress) GZIPInputStream(it) else it }
}
- public void delete() {
- delete.update(nodeId, createdAt);
- }
+ fun schemData() = schemData(true)
- @AllArgsConstructor
- @Getter
- public enum SchematicFormat {
+ override fun delete() = useDb { super.delete() }
+
+ enum class SchematicFormat(val fileEnding: String) {
MCEDIT(".schematic"),
SPONGE_V2(".schem"),
SPONGE_V3(".schem");
-
- public final String fileEnding;
}
-}
+}
\ No newline at end of file
diff --git a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
index d1495b46..5117eb13 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/SchematicNode.kt
@@ -335,7 +335,7 @@ class SchematicNode(id: EntityID) : IntEntity(id) {
val members: Set by lazy { NodeMember.getNodeMembers(nodeId) }
private lateinit var breadcrumbs: String
- fun getFileEnding(): String = checkDir { NodeData.getLatest(this).nodeFormat.fileEnding }
+ fun getFileEnding(): String = checkDir { NodeData.getLatest(this)!!.nodeFormat.fileEnding }
fun getId() = nodeId
fun isDir() = nodeType == null
diff --git a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt
index 11bc2e4d..14dcd201 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/UserConfig.kt
@@ -32,10 +32,14 @@ import java.util.UUID
object UserConfigTable: CompositeIdTable("UserConfig") {
val userId = reference("User", SteamwarUserTable)
- val config = varchar("Config", 32)
+ val config = varchar("Config", 32).entityId()
val value = text("Value", eagerLoading = true)
override val primaryKey = PrimaryKey(userId, config)
+
+ init {
+ addIdColumn(userId)
+ }
}
class UserConfig(id: EntityID): CompositeEntity(id) {
diff --git a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt
index 4da6e413..735d4e22 100644
--- a/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt
+++ b/CommonCore/SQL/src/de/steamwar/sql/internal/KotlinDatabase.kt
@@ -23,6 +23,7 @@ import org.intellij.lang.annotations.Language
import org.jetbrains.exposed.v1.core.ColumnType
import org.jetbrains.exposed.v1.core.Expression
import org.jetbrains.exposed.v1.core.ResultRow
+import org.jetbrains.exposed.v1.core.StdOutSqlLogger
import org.jetbrains.exposed.v1.core.statements.StatementType
import org.jetbrains.exposed.v1.core.statements.api.RowApi
import org.jetbrains.exposed.v1.dao.IntEntity
@@ -64,7 +65,10 @@ object KotlinDatabase {
fun useDb(statement: JdbcTransaction.() -> T): T {
KotlinDatabase.ensureConnected()
- return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db, statement)
+ return TransactionManager.currentOrNull()?.statement() ?: transaction(KotlinDatabase.db) {
+ addLogger(StdOutSqlLogger)
+ statement()
+ }
}
fun IntEntityClass.fromSql(
diff --git a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt
index d429af5c..d1ada3fa 100644
--- a/WebsiteBackend/src/de/steamwar/routes/Schematic.kt
+++ b/WebsiteBackend/src/de/steamwar/routes/Schematic.kt
@@ -36,6 +36,7 @@ import kotlinx.serialization.Serializable
import java.io.BufferedInputStream
import java.io.ByteArrayInputStream
import java.io.DataInputStream
+import java.io.InputStream
import java.security.MessageDigest
import java.time.Duration
import java.time.Instant