summaryrefslogtreecommitdiff
path: root/src/main/kotlin/io/dico/parcels2/storage/exposed
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/io/dico/parcels2/storage/exposed')
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt10
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedExtensions.kt148
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt328
-rw-r--r--src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt222
4 files changed, 355 insertions, 353 deletions
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt
index e49be79..d9e3071 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedBacking.kt
@@ -72,9 +72,11 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
override fun init() {
synchronized {
if (isShutdown || isConnected) throw IllegalStateException()
- dataSource = dataSourceFactory()
- database = Database.connect(dataSource!!)
- transaction(database!!) {
+ val dataSource = dataSourceFactory()
+ this.dataSource = dataSource
+ val database = Database.connect(dataSource)
+ this.database = database
+ transaction(database) {
create(WorldsT, ProfilesT, ParcelsT, ParcelOptionsT, PrivilegesLocalT, PrivilegesGlobalT)
}
}
@@ -84,7 +86,7 @@ class ExposedBacking(private val dataSourceFactory: () -> DataSource, val poolSi
synchronized {
if (isShutdown) throw IllegalStateException()
isShutdown = true
- coroutineContext[Job]!!.cancel(CancellationException("ExposedBacking shutdown"))
+ coroutineContext.cancel(CancellationException("ExposedBacking shutdown"))
dataSource?.let {
(it as? HikariDataSource)?.close()
}
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedExtensions.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedExtensions.kt
index 0245625..7640c0c 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedExtensions.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ExposedExtensions.kt
@@ -1,74 +1,74 @@
-package io.dico.parcels2.storage.exposed
-
-import org.jetbrains.exposed.sql.*
-import org.jetbrains.exposed.sql.Function
-import org.jetbrains.exposed.sql.statements.InsertStatement
-import org.jetbrains.exposed.sql.transactions.TransactionManager
-
-class UpsertStatement<Key : Any>(table: Table, conflictColumn: Column<*>? = null, conflictIndex: Index? = null) : InsertStatement<Key>(table, false) {
- val indexName: String
- val indexColumns: List<Column<*>>
-
- init {
- when {
- conflictIndex != null -> {
- indexName = conflictIndex.indexName
- indexColumns = conflictIndex.columns
- }
- conflictColumn != null -> {
- indexName = conflictColumn.name
- indexColumns = listOf(conflictColumn)
- }
- else -> throw IllegalArgumentException()
- }
- }
-
- override fun prepareSQL(transaction: Transaction) = buildString {
- append(super.prepareSQL(transaction))
-
- val dialect = transaction.db.vendor
- if (dialect == "postgresql") {
-
- append(" ON CONFLICT(")
- append(indexName)
- append(") DO UPDATE SET ")
-
- values.keys.filter { it !in indexColumns }.joinTo(this) { "${transaction.identity(it)}=EXCLUDED.${transaction.identity(it)}" }
-
- } else {
-
- append(" ON DUPLICATE KEY UPDATE ")
- values.keys.filter { it !in indexColumns }.joinTo(this) { "${transaction.identity(it)}=VALUES(${transaction.identity(it)})" }
-
- }
- }
-
-}
-
-inline fun <T : Table> T.upsert(conflictColumn: Column<*>? = null, conflictIndex: Index? = null, body: T.(UpsertStatement<Number>) -> Unit) =
- UpsertStatement<Number>(this, conflictColumn, conflictIndex).apply {
- body(this)
- execute(TransactionManager.current())
- }
-
-fun Table.indexR(customIndexName: String? = null, isUnique: Boolean = false, vararg columns: Column<*>): Index {
- val index = Index(columns.toList(), isUnique, customIndexName)
- indices.add(index)
- return index
-}
-
-fun Table.uniqueIndexR(customIndexName: String? = null, vararg columns: Column<*>): Index = indexR(customIndexName, true, *columns)
-
-fun <T : Int?> ExpressionWithColumnType<T>.abs(): Function<T> = Abs(this)
-
-class Abs<T : Int?>(val expr: Expression<T>) : Function<T>(IntegerColumnType()) {
- override fun toSQL(queryBuilder: QueryBuilder): String = "ABS(${expr.toSQL(queryBuilder)})"
-}
-
-fun <T : Comparable<T>> greaterOf(col1: ExpressionWithColumnType<T>, col2: ExpressionWithColumnType<T>): Expression<T> =
- with(SqlExpressionBuilder) {
- case(col1)
- .When(col1.greater(col2), col1)
- .Else(col2)
- }
-
+package io.dico.parcels2.storage.exposed
+
+import org.jetbrains.exposed.sql.*
+import org.jetbrains.exposed.sql.Function
+import org.jetbrains.exposed.sql.statements.InsertStatement
+import org.jetbrains.exposed.sql.transactions.TransactionManager
+
+class UpsertStatement<Key : Any>(table: Table, conflictColumn: Column<*>? = null, conflictIndex: Index? = null) : InsertStatement<Key>(table, false) {
+ val indexName: String
+ val indexColumns: List<Column<*>>
+
+ init {
+ when {
+ conflictIndex != null -> {
+ indexName = conflictIndex.indexName
+ indexColumns = conflictIndex.columns
+ }
+ conflictColumn != null -> {
+ indexName = conflictColumn.name
+ indexColumns = listOf(conflictColumn)
+ }
+ else -> throw IllegalArgumentException()
+ }
+ }
+
+ override fun prepareSQL(transaction: Transaction) = buildString {
+ append(super.prepareSQL(transaction))
+
+ val dialect = transaction.db.vendor
+ if (dialect == "postgresql") {
+
+ append(" ON CONFLICT(")
+ append(indexName)
+ append(") DO UPDATE SET ")
+
+ values.keys.filter { it !in indexColumns }.joinTo(this) { "${transaction.identity(it)}=EXCLUDED.${transaction.identity(it)}" }
+
+ } else {
+
+ append(" ON DUPLICATE KEY UPDATE ")
+ values.keys.filter { it !in indexColumns }.joinTo(this) { "${transaction.identity(it)}=VALUES(${transaction.identity(it)})" }
+
+ }
+ }
+
+}
+
+inline fun <T : Table> T.upsert(conflictColumn: Column<*>? = null, conflictIndex: Index? = null, body: T.(UpsertStatement<Number>) -> Unit) =
+ UpsertStatement<Number>(this, conflictColumn, conflictIndex).apply {
+ body(this)
+ execute(TransactionManager.current())
+ }
+
+fun Table.indexR(customIndexName: String? = null, isUnique: Boolean = false, vararg columns: Column<*>): Index {
+ val index = Index(columns.toList(), isUnique, customIndexName)
+ indices.add(index)
+ return index
+}
+
+fun Table.uniqueIndexR(customIndexName: String? = null, vararg columns: Column<*>): Index = indexR(customIndexName, true, *columns)
+
+fun <T : Int?> ExpressionWithColumnType<T>.abs(): Function<T> = Abs(this)
+
+class Abs<T : Int?>(val expr: Expression<T>) : Function<T>(IntegerColumnType()) {
+ override fun toSQL(queryBuilder: QueryBuilder): String = "ABS(${expr.toSQL(queryBuilder)})"
+}
+
+fun <T : Comparable<T>> greaterOf(col1: ExpressionWithColumnType<T>, col2: ExpressionWithColumnType<T>): Expression<T> =
+ with(SqlExpressionBuilder) {
+ case(col1)
+ .When(col1.greater(col2), col1)
+ .Else(col2)
+ }
+
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 6f6ad6b..8428b3a 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/IdTables.kt
@@ -1,165 +1,165 @@
-@file:Suppress("NOTHING_TO_INLINE", "PARAMETER_NAME_CHANGED_ON_OVERRIDE", "unused", "MemberVisibilityCanBePrivate")
-
-package io.dico.parcels2.storage.exposed
-
-import io.dico.parcels2.ParcelId
-import io.dico.parcels2.ParcelWorldId
-import io.dico.parcels2.PlayerProfile
-import io.dico.parcels2.storage.toByteArray
-import io.dico.parcels2.storage.toUUID
-import org.jetbrains.exposed.sql.*
-import org.jetbrains.exposed.sql.statements.UpdateBuilder
-import org.joda.time.DateTime
-import java.util.UUID
-
-abstract class IdTransactionsTable<TableT : IdTransactionsTable<TableT, QueryObj>, QueryObj>(tableName: String, columnName: String)
- : Table(tableName) {
- val id = integer(columnName).autoIncrement().primaryKey()
-
- @Suppress("UNCHECKED_CAST")
- inline val table: TableT
- get() = this as TableT
-
- internal inline fun getId(where: SqlExpressionBuilder.(TableT) -> Op<Boolean>): Int? {
- return select { where(table) }.firstOrNull()?.let { it[id] }
- }
-
- 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 number")
- }
-
- abstract fun getId(obj: QueryObj): Int?
- abstract fun getOrInitId(obj: QueryObj): Int
- 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>("parcels_worlds", "world_id") {
- val name = varchar("name", 50)
- val uid = binary("uid", 16).nullable()
- val creation_time = datetime("creation_time").nullable()
- val index_name = uniqueIndexR("index_name", name)
- val index_uid = uniqueIndexR("index_uid", uid)
-
- 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 ->
- 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 getItem(row: ResultRow): ParcelWorldId {
- return ParcelWorldId(row[name], row[uid]?.toUUID())
- }
-
- fun getWorldCreationTime(worldId: ParcelWorldId): DateTime? {
- val id = getId(worldId) ?: return null
- return select { WorldsT.id eq id }.firstOrNull()?.let { it[WorldsT.creation_time] }
- }
-
- fun setWorldCreationTime(worldId: ParcelWorldId, time: DateTime) {
- val id = getOrInitId(worldId)
- update({ WorldsT.id eq id }) {
- it[WorldsT.creation_time] = time
- }
- }
-}
-
-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(ProfilesT.id).nullable()
- val sign_oudated = bool("sign_outdated").default(false)
- val claim_time = datetime("claim_time").nullable()
- val index_location = uniqueIndexR("index_location", world_id, px, pz)
-
- private inline fun getId(worldId: Int, parcelX: Int, parcelZ: Int): Int? = getId { world_id.eq(worldId) and px.eq(parcelX) and pz.eq(parcelZ) }
- 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 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)
- override fun getOrInitId(parcel: ParcelId): Int = getOrInitId(parcel.worldId.name, parcel.worldId.uid, parcel.x, parcel.z)
-
- 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 getItem(row: ResultRow): ParcelId? {
- val worldId = row[world_id]
- val world = WorldsT.getItem(worldId) ?: return null
- return ParcelId(world, row[px], row[pz])
- }
-}
-
-object ProfilesT : IdTransactionsTable<ProfilesT, PlayerProfile>("parcels_profiles", "owner_id") {
- val uuid = binary("uuid", 16).nullable()
- val name = varchar("name", 32).nullable()
-
- // MySQL dialect MUST permit multiple null values for this to work. Server SQL does not allow this. That dialect is shit anyway.
- val uuid_constraint = uniqueIndexR("uuid_constraint", uuid)
- 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.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 ->
- getOrInitId(
- { getId(binaryUuid) },
- { it[this@ProfilesT.uuid] = binaryUuid; it[this@ProfilesT.name] = name },
- { "profile(uuid = $uuid, name = $name)" })
- }
-
- private inline fun getOrInitId(name: String) = getOrInitId(
- { getId(name) },
- { it[ProfilesT.name] = name },
- { "owner(name = $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.nameOrBukkitName)
- is PlayerProfile.Fake -> getOrInitId(profile.name)
- else -> throw IllegalArgumentException() // Unresolved profiles cannot be added to the database
- }
-
- 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
- }
-
- /*
- fun updatePlayerProfile(profile: PlayerProfile.Real) {
- update({ uuid eq profile.uuid.toByteArray() }) {
- it[name] = profile.nameOrBukkitName
- }
- }*/
-
-}
-
+@file:Suppress("NOTHING_TO_INLINE", "PARAMETER_NAME_CHANGED_ON_OVERRIDE", "unused", "MemberVisibilityCanBePrivate")
+
+package io.dico.parcels2.storage.exposed
+
+import io.dico.parcels2.ParcelId
+import io.dico.parcels2.ParcelWorldId
+import io.dico.parcels2.PlayerProfile
+import io.dico.parcels2.storage.toByteArray
+import io.dico.parcels2.storage.toUUID
+import org.jetbrains.exposed.sql.*
+import org.jetbrains.exposed.sql.statements.UpdateBuilder
+import org.joda.time.DateTime
+import java.util.UUID
+
+abstract class IdTransactionsTable<TableT : IdTransactionsTable<TableT, QueryObj>, QueryObj>(tableName: String, columnName: String)
+ : Table(tableName) {
+ val id = integer(columnName).autoIncrement().primaryKey()
+
+ @Suppress("UNCHECKED_CAST")
+ inline val table: TableT
+ get() = this as TableT
+
+ internal inline fun getId(where: SqlExpressionBuilder.(TableT) -> Op<Boolean>): Int? {
+ return select { where(table) }.firstOrNull()?.let { it[id] }
+ }
+
+ 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 number")
+ }
+
+ abstract fun getId(obj: QueryObj): Int?
+ abstract fun getOrInitId(obj: QueryObj): Int
+ 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>("parcels_worlds", "world_id") {
+ val name = varchar("name", 50)
+ val uid = binary("uid", 16).nullable()
+ val creation_time = datetime("creation_time").nullable()
+ val index_name = uniqueIndexR("index_name", name)
+ val index_uid = uniqueIndexR("index_uid", uid)
+
+ 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 ->
+ 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 getItem(row: ResultRow): ParcelWorldId {
+ return ParcelWorldId(row[name], row[uid]?.toUUID())
+ }
+
+ fun getWorldCreationTime(worldId: ParcelWorldId): DateTime? {
+ val id = getId(worldId) ?: return null
+ return select { WorldsT.id eq id }.firstOrNull()?.let { it[WorldsT.creation_time] }
+ }
+
+ fun setWorldCreationTime(worldId: ParcelWorldId, time: DateTime) {
+ val id = getOrInitId(worldId)
+ update({ WorldsT.id eq id }) {
+ it[WorldsT.creation_time] = time
+ }
+ }
+}
+
+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(ProfilesT.id).nullable()
+ val sign_oudated = bool("sign_outdated").default(false)
+ val claim_time = datetime("claim_time").nullable()
+ val index_location = uniqueIndexR("index_location", world_id, px, pz)
+
+ private inline fun getId(worldId: Int, parcelX: Int, parcelZ: Int): Int? = getId { world_id.eq(worldId) and px.eq(parcelX) and pz.eq(parcelZ) }
+ 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 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)
+ override fun getOrInitId(parcel: ParcelId): Int = getOrInitId(parcel.worldId.name, parcel.worldId.uid, parcel.x, parcel.z)
+
+ 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 getItem(row: ResultRow): ParcelId? {
+ val worldId = row[world_id]
+ val world = WorldsT.getItem(worldId) ?: return null
+ return ParcelId(world, row[px], row[pz])
+ }
+}
+
+object ProfilesT : IdTransactionsTable<ProfilesT, PlayerProfile>("parcels_profiles", "owner_id") {
+ val uuid = binary("uuid", 16).nullable()
+ val name = varchar("name", 32).nullable()
+
+ // MySQL dialect MUST permit multiple null values for this to work. Server SQL does not allow this. That dialect is shit anyway.
+ val uuid_constraint = uniqueIndexR("uuid_constraint", uuid)
+ 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.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 ->
+ getOrInitId(
+ { getId(binaryUuid) },
+ { it[this@ProfilesT.uuid] = binaryUuid; it[this@ProfilesT.name] = name },
+ { "profile(uuid = $uuid, name = $name)" })
+ }
+
+ private inline fun getOrInitId(name: String) = getOrInitId(
+ { getId(name) },
+ { it[ProfilesT.name] = name },
+ { "owner(name = $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.nameOrBukkitName)
+ is PlayerProfile.Fake -> getOrInitId(profile.name)
+ else -> throw IllegalArgumentException() // Unresolved profiles cannot be added to the database
+ }
+
+ 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
+ }
+
+ /*
+ fun updatePlayerProfile(profile: PlayerProfile.Real) {
+ update({ uuid eq profile.uuid.toByteArray() }) {
+ it[name] = profile.nameOrBukkitName
+ }
+ }*/
+
+}
+
// val ParcelsWithOptionsT = ParcelsT.join(ParcelOptionsT, JoinType.INNER, onColumn = ParcelsT.id, otherColumn = ParcelOptionsT.parcel_id) \ No newline at end of file
diff --git a/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt b/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt
index b9d16fc..26cfc7a 100644
--- a/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt
+++ b/src/main/kotlin/io/dico/parcels2/storage/exposed/ListTables.kt
@@ -1,111 +1,111 @@
-@file:Suppress("PropertyName", "LocalVariableName", "NOTHING_TO_INLINE")
-
-package io.dico.parcels2.storage.exposed
-
-import io.dico.parcels2.*
-import io.dico.parcels2.Privilege.DEFAULT
-import io.dico.parcels2.util.ext.alsoIfTrue
-import kotlinx.coroutines.channels.SendChannel
-import org.jetbrains.exposed.sql.*
-
-object PrivilegesLocalT : PrivilegesTable<ParcelId>("parcels_privilege_local", ParcelsT)
-object PrivilegesGlobalT : PrivilegesTable<PlayerProfile>("parcels_privilege_global", ProfilesT)
-
-object ParcelOptionsT : Table("parcels_options") {
- val parcel_id = integer("parcel_id").primaryKey().references(ParcelsT.id, ReferenceOption.CASCADE)
- val interact_bitmask = binary("interact_bitmask", 4)
-}
-
-typealias PrivilegesSendChannel<AttachT> = SendChannel<Pair<AttachT, PrivilegesHolder>>
-
-sealed class PrivilegesTable<AttachT>(name: String, val idTable: IdTransactionsTable<*, AttachT>) : Table(name) {
- val attach_id = integer("attach_id").references(idTable.id, ReferenceOption.CASCADE)
- val profile_id = integer("profile_id").references(ProfilesT.id, ReferenceOption.CASCADE)
- val privilege = integer("privilege")
- val index_pair = uniqueIndexR("index_pair", attach_id, profile_id)
-
- fun setPrivilege(attachedOn: AttachT, player: PlayerProfile.Real, privilege: Privilege) {
- privilege.requireNonTransient()
-
- if (privilege == DEFAULT) {
- val player_id = ProfilesT.getId(player) ?: return
- idTable.getId(attachedOn)?.let { holder ->
- deleteWhere { (attach_id eq holder) and (profile_id eq player_id) }
- }
- return
- }
-
- val holder = idTable.getOrInitId(attachedOn)
- val player_id = ProfilesT.getOrInitId(player)
- upsert(conflictIndex = index_pair) {
- it[attach_id] = holder
- it[profile_id] = player_id
- it[this.privilege] = privilege.number
- }
- }
-
- fun readPrivileges(id: Int): PrivilegesHolder? {
- val list = slice(profile_id, privilege).select { attach_id eq id }
- val result = PrivilegesHolder()
- for (row in list) {
- val profile = ProfilesT.getRealItem(row[profile_id]) ?: continue
- result.setRawStoredPrivilege(profile, Privilege.getByNumber(row[privilege]) ?: continue)
- }
- return result
- }
-
- fun sendAllPrivilegesH(channel: PrivilegesSendChannel<AttachT>) {
- val iterator = selectAll().orderBy(attach_id).iterator()
-
- if (iterator.hasNext()) {
- var row = iterator.next()
- var id: Int = row[attach_id]
- var attach: AttachT? = null
- var map: PrivilegesHolder? = null
-
- fun initAttachAndMap() {
- attach = idTable.getItem(id)
- map = attach?.let { PrivilegesHolder() }
- }
-
- fun sendIfPresent() {
- if (attach != null && map != null) {
- channel.offer(attach!! to map!!)
- }
- attach = null
- map = null
- }
-
- initAttachAndMap()
-
- do {
- val rowId = row[attach_id]
- if (rowId != id) {
- sendIfPresent()
- id = rowId
- initAttachAndMap()
- }
-
- if (attach == null) {
- continue // owner not found for this owner id
- }
-
- val profile = ProfilesT.getRealItem(row[profile_id])
- if (profile == null) {
- logger.error("Privilege from database is null, id ${row[profile_id]}")
- continue
- }
- val privilege = Privilege.getByNumber(row[privilege])
- if (privilege == null) {
- logger.error("Privilege from database is null, number ${row[this.privilege]}")
- continue
- }
- map!!.setRawStoredPrivilege(profile, privilege)
-
- } while (iterator.hasNext().alsoIfTrue { row = iterator.next() })
-
- sendIfPresent()
- }
- }
-
-}
+@file:Suppress("PropertyName", "LocalVariableName", "NOTHING_TO_INLINE")
+
+package io.dico.parcels2.storage.exposed
+
+import io.dico.parcels2.*
+import io.dico.parcels2.Privilege.DEFAULT
+import io.dico.parcels2.util.ext.alsoIfTrue
+import kotlinx.coroutines.channels.SendChannel
+import org.jetbrains.exposed.sql.*
+
+object PrivilegesLocalT : PrivilegesTable<ParcelId>("parcels_privilege_local", ParcelsT)
+object PrivilegesGlobalT : PrivilegesTable<PlayerProfile>("parcels_privilege_global", ProfilesT)
+
+object ParcelOptionsT : Table("parcels_options") {
+ val parcel_id = integer("parcel_id").primaryKey().references(ParcelsT.id, ReferenceOption.CASCADE)
+ val interact_bitmask = binary("interact_bitmask", 4)
+}
+
+typealias PrivilegesSendChannel<AttachT> = SendChannel<Pair<AttachT, PrivilegesHolder>>
+
+sealed class PrivilegesTable<AttachT>(name: String, val idTable: IdTransactionsTable<*, AttachT>) : Table(name) {
+ val attach_id = integer("attach_id").references(idTable.id, ReferenceOption.CASCADE)
+ val profile_id = integer("profile_id").references(ProfilesT.id, ReferenceOption.CASCADE)
+ val privilege = integer("privilege")
+ val index_pair = uniqueIndexR("index_pair", attach_id, profile_id)
+
+ fun setPrivilege(attachedOn: AttachT, player: PlayerProfile.Real, privilege: Privilege) {
+ privilege.requireNonTransient()
+
+ if (privilege == DEFAULT) {
+ val player_id = ProfilesT.getId(player) ?: return
+ idTable.getId(attachedOn)?.let { holder ->
+ deleteWhere { (attach_id eq holder) and (profile_id eq player_id) }
+ }
+ return
+ }
+
+ val holder = idTable.getOrInitId(attachedOn)
+ val player_id = ProfilesT.getOrInitId(player)
+ upsert(conflictIndex = index_pair) {
+ it[attach_id] = holder
+ it[profile_id] = player_id
+ it[this.privilege] = privilege.number
+ }
+ }
+
+ fun readPrivileges(id: Int): PrivilegesHolder? {
+ val list = slice(profile_id, privilege).select { attach_id eq id }
+ val result = PrivilegesHolder()
+ for (row in list) {
+ val profile = ProfilesT.getRealItem(row[profile_id]) ?: continue
+ result.setRawStoredPrivilege(profile, Privilege.getByNumber(row[privilege]) ?: continue)
+ }
+ return result
+ }
+
+ fun sendAllPrivilegesH(channel: PrivilegesSendChannel<AttachT>) {
+ val iterator = selectAll().orderBy(attach_id).iterator()
+
+ if (iterator.hasNext()) {
+ var row = iterator.next()
+ var id: Int = row[attach_id]
+ var attach: AttachT? = null
+ var map: PrivilegesHolder? = null
+
+ fun initAttachAndMap() {
+ attach = idTable.getItem(id)
+ map = attach?.let { PrivilegesHolder() }
+ }
+
+ fun sendIfPresent() {
+ if (attach != null && map != null) {
+ channel.offer(attach!! to map!!)
+ }
+ attach = null
+ map = null
+ }
+
+ initAttachAndMap()
+
+ do {
+ val rowId = row[attach_id]
+ if (rowId != id) {
+ sendIfPresent()
+ id = rowId
+ initAttachAndMap()
+ }
+
+ if (attach == null) {
+ continue // owner not found for this owner id
+ }
+
+ val profile = ProfilesT.getRealItem(row[profile_id])
+ if (profile == null) {
+ logger.error("Privilege from database is null, id ${row[profile_id]}")
+ continue
+ }
+ val privilege = Privilege.getByNumber(row[privilege])
+ if (privilege == null) {
+ logger.error("Privilege from database is null, number ${row[this.privilege]}")
+ continue
+ }
+ map!!.setRawStoredPrivilege(profile, privilege)
+
+ } while (iterator.hasNext().alsoIfTrue { row = iterator.next() })
+
+ sendIfPresent()
+ }
+ }
+
+}