diff options
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt')
-rw-r--r-- | src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt | 85 |
1 files changed, 52 insertions, 33 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt index ac6e431..33314aa 100644 --- a/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt +++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt @@ -3,12 +3,12 @@ package io.dico.parcels2.storage.exposed import io.dico.parcels2.ParcelId -import io.dico.parcels2.ParcelOwner import io.dico.parcels2.ParcelWorldId +import io.dico.parcels2.PlayerProfile import io.dico.parcels2.util.toByteArray import io.dico.parcels2.util.toUUID import org.jetbrains.exposed.sql.* -import org.jetbrains.exposed.sql.statements.InsertStatement +import org.jetbrains.exposed.sql.statements.UpdateBuilder import java.util.UUID sealed class IdTransactionsTable<TableT : IdTransactionsTable<TableT, QueryObj>, QueryObj>(tableName: String, columnName: String) @@ -23,16 +23,16 @@ sealed class IdTransactionsTable<TableT : IdTransactionsTable<TableT, QueryObj>, return select { where(table) }.firstOrNull()?.let { it[id] } } - internal inline fun insertAndGetId(objName: String, noinline body: TableT.(InsertStatement<Number>) -> Unit): Int { - return table.insert(body)[id] ?: insertError(objName) + internal inline fun getOrInitId(getId: () -> Int?, noinline body: TableT.(UpdateBuilder<*>) -> Unit, objName: () -> String): Int { + return getId() ?: table.insertIgnore(body)[id] ?: getId() ?: throw ExposedDatabaseException("This should not happen - failed to insert ${objName()} and get its id") } - private inline fun insertError(obj: String): Nothing = throw ExposedDatabaseException("This should not happen - failed to insert $obj and getParcelDeferred its id") - abstract fun getId(obj: QueryObj): Int? abstract fun getOrInitId(obj: QueryObj): Int - fun getId(id: Int): QueryObj? = select { this@IdTransactionsTable.id eq id }.firstOrNull()?.let { getId(it) } - abstract fun getId(row: ResultRow): QueryObj? + fun getItem(id: Int): QueryObj? = select { this@IdTransactionsTable.id eq id }.firstOrNull()?.let { getItem(it) } + abstract fun getItem(row: ResultRow): QueryObj? + + fun getId(obj: QueryObj, init: Boolean): Int? = if (init) getOrInitId(obj) else getId(obj) } object WorldsT : IdTransactionsTable<WorldsT, ParcelWorldId>("parcel_worlds", "world_id") { @@ -44,14 +44,16 @@ object WorldsT : IdTransactionsTable<WorldsT, ParcelWorldId>("parcel_worlds", "w internal inline fun getId(worldName: String, binaryUid: ByteArray?): Int? = getId { (name eq worldName).let { if (binaryUid == null) it else it or (uid eq binaryUid) } } internal inline fun getId(worldName: String, uid: UUID?): Int? = getId(worldName, uid?.toByteArray()) internal inline fun getOrInitId(worldName: String, worldUid: UUID?): Int = worldUid?.toByteArray().let { binaryUid -> - getId(worldName, binaryUid) - ?: insertAndGetId("world named $worldName") { it[name] = worldName; binaryUid?.let { buid -> it[uid] = buid } } + return getOrInitId( + { getId(worldName, binaryUid) }, + { it[name] = worldName; it[uid] = binaryUid }, + { "world named $worldName" }) } override fun getId(world: ParcelWorldId): Int? = getId(world.name, world.uid) override fun getOrInitId(world: ParcelWorldId): Int = getOrInitId(world.name, world.uid) - override fun getId(row: ResultRow): ParcelWorldId { + override fun getItem(row: ResultRow): ParcelWorldId { return ParcelWorldId(row[name], row[uid]?.toUUID()) } } @@ -60,7 +62,7 @@ object ParcelsT : IdTransactionsTable<ParcelsT, ParcelId>("parcels", "parcel_id" val world_id = integer("world_id").references(WorldsT.id) val px = integer("px") val pz = integer("pz") - val owner_id = integer("owner_id").references(OwnersT.id).nullable() + val owner_id = integer("owner_id").references(ProfilesT.id).nullable() val claim_time = datetime("claim_time").nullable() val index_location = uniqueIndexR("index_location", world_id, px, pz) @@ -68,8 +70,10 @@ object ParcelsT : IdTransactionsTable<ParcelsT, ParcelId>("parcels", "parcel_id" private inline fun getId(worldName: String, worldUid: UUID?, parcelX: Int, parcelZ: Int): Int? = WorldsT.getId(worldName, worldUid)?.let { getId(it, parcelX, parcelZ) } private inline fun getOrInitId(worldName: String, worldUid: UUID?, parcelX: Int, parcelZ: Int): Int { val worldId = WorldsT.getOrInitId(worldName, worldUid) - return getId(worldId, parcelX, parcelZ) - ?: insertAndGetId("parcel at $worldName($parcelX, $parcelZ)") { it[world_id] = worldId; it[px] = parcelX; it[pz] = parcelZ } + return getOrInitId( + { getId(worldId, parcelX, parcelZ) }, + { it[world_id] = worldId; it[px] = parcelX; it[pz] = parcelZ }, + { "parcel at $worldName($parcelX, $parcelZ)" }) } override fun getId(parcel: ParcelId): Int? = getId(parcel.worldId.name, parcel.worldId.uid, parcel.x, parcel.z) @@ -78,41 +82,56 @@ object ParcelsT : IdTransactionsTable<ParcelsT, ParcelId>("parcels", "parcel_id" private inline fun getRow(id: Int): ResultRow? = select { ParcelsT.id eq id }.firstOrNull() fun getRow(parcel: ParcelId): ResultRow? = getId(parcel)?.let { getRow(it) } - override fun getId(row: ResultRow): ParcelId? { + override fun getItem(row: ResultRow): ParcelId? { val worldId = row[world_id] - val world = WorldsT.getId(worldId) ?: return null + val world = WorldsT.getItem(worldId) ?: return null return ParcelId(world, row[px], row[pz]) } } -object OwnersT : IdTransactionsTable<OwnersT, ParcelOwner>("parcel_owners", "owner_id") { +object ProfilesT : IdTransactionsTable<ProfilesT, PlayerProfile>("parcel_profiles", "owner_id") { val uuid = binary("uuid", 16).nullable() val name = varchar("name", 32) val index_pair = uniqueIndexR("index_pair", uuid, name) private inline fun getId(binaryUuid: ByteArray) = getId { uuid eq binaryUuid } private inline fun getId(uuid: UUID) = getId(uuid.toByteArray()) - private inline fun getId(nameIn: String) = getId { uuid.isNull() and (name eq nameIn) } + private inline fun getId(nameIn: String) = getId { uuid.isNull() and (name.lowerCase() eq nameIn.toLowerCase()) } + private inline fun getRealId(nameIn: String) = getId { uuid.isNotNull() and (name.lowerCase() eq nameIn.toLowerCase()) } - private inline fun getOrInitId(uuid: UUID, name: String) = uuid.toByteArray().let { binaryUuid -> - getId(binaryUuid) ?: insertAndGetId("owner(uuid = $uuid)") { - it[this@OwnersT.uuid] = binaryUuid - it[this@OwnersT.name] = name - } + private inline fun getOrInitId(uuid: UUID, name: String) = uuid.toByteArray().let { binaryUuid -> getOrInitId( + { getId(binaryUuid) }, + { it[this@ProfilesT.uuid] = binaryUuid; it[this@ProfilesT.name] = name }, + { "profile(uuid = $uuid, name = $name)" }) } - private inline fun getOrInitId(name: String) = - getId(name) ?: insertAndGetId("owner(name = $name)") { it[OwnersT.name] = name } + private inline fun getOrInitId(name: String) = getOrInitId( + { getId(name) }, + { it[ProfilesT.name] = name }, + { "owner(name = $name)" }) - override fun getId(owner: ParcelOwner): Int? = - if (owner.hasUUID) getId(owner.uuid!!) - else getId(owner.name!!) - override fun getOrInitId(owner: ParcelOwner): Int = - if (owner.hasUUID) getOrInitId(owner.uuid!!, owner.notNullName) - else getOrInitId(owner.name!!) + override fun getId(profile: PlayerProfile): Int? = when (profile) { + is PlayerProfile.Real -> getId(profile.uuid) + is PlayerProfile.Fake -> getId(profile.name) + is PlayerProfile.Unresolved -> getRealId(profile.name) + else -> throw IllegalArgumentException() + } + + override fun getOrInitId(profile: PlayerProfile): Int = when (profile) { + is PlayerProfile.Real -> getOrInitId(profile.uuid, profile.notNullName) + is PlayerProfile.Fake -> getOrInitId(profile.name) + else -> throw IllegalArgumentException() + } - override fun getId(row: ResultRow): ParcelOwner { - return row[uuid]?.toUUID()?.let { ParcelOwner(it) } ?: ParcelOwner(row[name]) + override fun getItem(row: ResultRow): PlayerProfile { + return PlayerProfile(row[uuid]?.toUUID(), row[name]) } + + fun getRealItem(id: Int): PlayerProfile.Real? { + return getItem(id) as? PlayerProfile.Real + } + } + +// val ParcelsWithOptionsT = ParcelsT.join(ParcelOptionsT, JoinType.INNER, onColumn = ParcelsT.id, otherColumn = ParcelOptionsT.parcel_id)
\ No newline at end of file |