Skip to content

Commit

Permalink
Add more data types (#8)
Browse files Browse the repository at this point in the history
* Add more data types

* Adjust tests

* Add minecraft color test

* Add missing tests

* Organize imports
  • Loading branch information
MineKing9534 authored Oct 26, 2024
1 parent 0b47ecf commit 256939e
Show file tree
Hide file tree
Showing 13 changed files with 227 additions and 12 deletions.
1 change: 0 additions & 1 deletion core/src/main/kotlin/de/mineking/database/Nodes.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package de.mineking.database

import org.jdbi.v3.core.argument.Argument
import javax.swing.text.html.StyleSheet.BoxPainter
import kotlin.reflect.KType
import kotlin.reflect.full.isSubtypeOf
import kotlin.reflect.jvm.jvmErasure
Expand Down
21 changes: 18 additions & 3 deletions discord/src/main/kotlin/de/mineking/database/DiscordMappers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ enum class SnowflakeType(val getter: (JDA, Long) -> ISnowflake?) {
}
}

internal inline fun <reified T> DatabaseConnection.registerDiscordMappers(bot: JDA, mapper: TypeMapper<T?, *>, enumMapper: TypeMapper<Enum<*>?, *>?, crossinline converter: (T) -> Long, crossinline extractor: (ISnowflake?) -> T?) {
internal inline fun <reified T> DatabaseConnection.registerDiscordMappers(
bot: JDA,
enumMapper: TypeMapper<Enum<*>?, *>? = null,
mapper: TypeMapper<T?, *>,
crossinline converter: (T) -> Long,
crossinline extractor: (ISnowflake?) -> T?
) {
data["bot"] = bot

if (enumMapper != null) {
Expand Down Expand Up @@ -67,5 +73,14 @@ internal inline fun <reified T> DatabaseConnection.registerDiscordMappers(bot: J
typeMappers += typeMapper<User?, T?>(mapper, { it?.let { bot.getUserById(converter(it)) } }, extractor)
}

fun DatabaseConnection.registerDiscordLongMappers(bot: JDA, longType: TypeMapper<Long?, *>, enumType: TypeMapper<Enum<*>?, *>? = null) = registerDiscordMappers(bot, longType, enumType, { it }) { it?.idLong }
fun DatabaseConnection.registerDiscordStringMappers(bot: JDA, stringType: TypeMapper<String?, *>, enumType: TypeMapper<Enum<*>?, *>? = null) = registerDiscordMappers(bot, stringType, enumType, { it.toLong() }) { it?.id }
fun DatabaseConnection.registerDiscordLongMappers(
bot: JDA,
longType: TypeMapper<Long?, *>,
enumType: TypeMapper<Enum<*>?, *>? = null
) = registerDiscordMappers(bot, enumType, longType, { it }) { it?.idLong }

fun DatabaseConnection.registerDiscordStringMappers(
bot: JDA,
stringType: TypeMapper<String?, *>,
enumType: TypeMapper<Enum<*>?, *>? = null
) = registerDiscordMappers(bot, enumType, stringType, { it.toLong() }) { it?.id }
20 changes: 15 additions & 5 deletions minecraft/src/main/kotlin/de/mineking/database/MinecraftMappers.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.mineking.database

import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextColor
import org.bukkit.Location
import org.bukkit.Server
import org.bukkit.World
Expand All @@ -14,15 +16,23 @@ import kotlin.reflect.typeOf
@Retention(AnnotationRetention.RUNTIME)
annotation class LocationWorldColumn(val name: String)

fun DatabaseConnection.registerMinecraftMappers(server: Server, uuidType: TypeMapper<UUID?, *>, arrayType: TypeMapper<*, Array<*>?>, doubleType: TypeMapper<Double?, *>) {
fun DatabaseConnection.registerMinecraftMappers(
server: Server,
textType: TypeMapper<String?, *>? = null,
uuidType: TypeMapper<UUID?, *>? = null,
arrayType: TypeMapper<*, Array<*>?>? = null,
doubleType: TypeMapper<Double?, *>? = null
) {
data["server"] = server

typeMappers += typeMapper(uuidType, { it?.let { server.getOfflinePlayer(it) } }, { it?.uniqueId })
if (uuidType != null) typeMappers += typeMapper(uuidType, { it?.let { server.getOfflinePlayer(it) } }, { it?.uniqueId })
if (textType != null) typeMappers += typeMapper<TextColor?, String?>(textType, { it?.let { TextColor.fromHexString(it) } }, { it?.asHexString() })
if (textType != null) typeMappers += typeMapper(textType, { it?.let { NamedTextColor.NAMES.value(it.lowercase()) } }, { it?.let { NamedTextColor.NAMES.key(it)?.uppercase() } })

val worldMapper = typeMapper(uuidType, { it?.let { server.getWorld(it) } }, { it?.uid })
typeMappers += worldMapper
val worldMapper = if (uuidType != null) typeMapper(uuidType, { it?.let { server.getWorld(it) } }, { it?.uid }) else null
if (worldMapper != null) typeMappers += worldMapper

typeMappers += object : TypeMapper<Location?, Array<Double>?> {
if (worldMapper != null && doubleType != null && arrayType != null) typeMappers += object : TypeMapper<Location?, Array<Double>?> {
override fun accepts(manager: DatabaseConnection, property: KProperty<*>?, type: KType): Boolean = type.isSubtypeOf(typeOf<Location?>())
override fun getType(column: ColumnData<*, *>?, table: TableStructure<*>, type: KType): DataType = arrayType.getType(column, table, typeOf<Array<Double>>())

Expand Down
50 changes: 50 additions & 0 deletions minecraft/src/test/kotlin/tests/minecraft/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package tests.minecraft

import de.mineking.database.*
import de.mineking.database.vendors.postgres.PostgresConnection
import de.mineking.database.vendors.postgres.PostgresMappers
import net.kyori.adventure.text.format.NamedTextColor
import net.kyori.adventure.text.format.TextColor
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Test
import setup.ConsoleSqlLogger
import setup.createServer
import setup.recreate

data class ColorDao(
@AutoIncrement @Key @Column val id: Int = 0,
@Column val color: TextColor = TextColor.color(0),
@Column val namedColor: NamedTextColor = NamedTextColor.BLACK
)

class ColorTest {
val connection = PostgresConnection("localhost:5432/test", user = "test", password = "test")
val table: Table<ColorDao>

init {
connection.registerMinecraftMappers(createServer(), PostgresMappers.STRING, PostgresMappers.UUID_MAPPER, PostgresMappers.ARRAY, PostgresMappers.DOUBLE)
table = connection.getTable(name = "color_test") { ColorDao() }

table.recreate()

table.insert(ColorDao(color = TextColor.color(0x00ff00), namedColor = NamedTextColor.GREEN))

connection.driver.setSqlLogger(ConsoleSqlLogger)
}

@Test
fun selectAll() {
val result = table.select().list()

assertEquals(TextColor.color(0x00ff00), result[0].color)
assertEquals(NamedTextColor.GREEN, result[0].namedColor)
}

@Test
fun selectColumn() {
assertEquals(TextColor.color(0x00ff00), table.select<TextColor>(property("color"), limit = 1).first())
assertEquals(NamedTextColor.GREEN, table.select<NamedTextColor>(property("namedColor"), limit = 1).first())

assertEquals(1, table.selectRowCount(where = property("color") isEqualTo value(TextColor.color(0x00ff00))))
}
}
2 changes: 1 addition & 1 deletion minecraft/src/test/kotlin/tests/minecraft/Location.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class LocationTest {
)

init {
connection.registerMinecraftMappers(createServer(worlds = worlds), PostgresMappers.UUID_MAPPER, PostgresMappers.ARRAY, PostgresMappers.DOUBLE)
connection.registerMinecraftMappers(createServer(worlds = worlds), PostgresMappers.STRING, PostgresMappers.UUID_MAPPER, PostgresMappers.ARRAY, PostgresMappers.DOUBLE)
table = connection.getTable(name = "location_test") { LocationDao() }

table.recreate()
Expand Down
2 changes: 1 addition & 1 deletion minecraft/src/test/kotlin/tests/minecraft/Player.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class PlayerTest {
)

init {
connection.registerMinecraftMappers(createServer(players = players), PostgresMappers.UUID_MAPPER, PostgresMappers.ARRAY, PostgresMappers.DOUBLE)
connection.registerMinecraftMappers(createServer(players = players), PostgresMappers.STRING, PostgresMappers.UUID_MAPPER, PostgresMappers.ARRAY, PostgresMappers.DOUBLE)
table = connection.getTable(name = "player_test") { PlayerDao() }

table.recreate()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package de.mineking.database.vendors.postgres

import de.mineking.database.*
import de.mineking.database.Node
import de.mineking.database.Where
import de.mineking.database.invoke
import de.mineking.database.value
import kotlin.reflect.typeOf

fun arrayLength(node: Node) = "array_length"(node)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import de.mineking.database.*
import org.jdbi.v3.core.argument.Argument
import org.jdbi.v3.core.statement.StatementContext
import org.postgresql.util.PGobject
import java.awt.Color
import java.math.BigDecimal
import java.math.BigInteger
import java.sql.*
Expand Down Expand Up @@ -88,6 +89,9 @@ object PostgresMappers {
val ZONED_DATE_TIME = typeMapper<ZonedDateTime?>(PostgresType.TIMESTAMPTZ, { set, name -> set.getObject(name, OffsetDateTime::class.java).toZonedDateTime() }, { value, statement, position -> statement.setTimestamp(position, value?.let { Timestamp.valueOf(it.toLocalDateTime()) }) })
val LOCAL_DATE = typeMapper<LocalDate?>(PostgresType.DATE, { set, name -> set.getDate(name).toLocalDate() }, { value, statement, position -> statement.setDate(position, value?.let { Date.valueOf(it) }) })

val LOCALE = typeMapper(STRING, { it?.let { Locale.forLanguageTag(it) } }, { it?.toLanguageTag() })
val COLOR = typeMapper(INTEGER, { it?.let { Color(it, true) } }, { it?.rgb })

val ARRAY = object : TypeMapper<Any?, Array<*>?> {
fun Any.asArray(): Array<*> = when (this) {
is Array<*> -> this
Expand Down
32 changes: 32 additions & 0 deletions postgres/src/test/kotlin/tests/postgres/specific/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package tests.postgres.specific

import de.mineking.database.*
import de.mineking.database.vendors.postgres.PostgresConnection
import org.junit.jupiter.api.Test
import setup.ConsoleSqlLogger
import setup.recreate
import java.awt.Color
import kotlin.test.assertEquals

data class ColorDao(
@AutoIncrement @Key @Column val id: Int = 0,
@Column val color: Color = Color.WHITE
)

class ColorTest {
val connection = PostgresConnection("localhost:5432/test", user = "test", password = "test")
val table = connection.getTable(name = "color_test") { ColorDao() }

init {
table.recreate()

table.insert(ColorDao(color = Color.GREEN))

connection.driver.setSqlLogger(ConsoleSqlLogger)
}

@Test
fun selectAll() {
assertEquals(Color.GREEN, table.select<Color>(property("color")).first())
}
}
32 changes: 32 additions & 0 deletions postgres/src/test/kotlin/tests/postgres/specific/Locale.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package tests.postgres.specific

import de.mineking.database.*
import de.mineking.database.vendors.postgres.PostgresConnection
import org.junit.jupiter.api.Test
import setup.ConsoleSqlLogger
import setup.recreate
import java.util.*
import kotlin.test.assertEquals

data class LocaleDao(
@AutoIncrement @Key @Column val id: Int = 0,
@Column val locale: Locale = Locale.ENGLISH,
)

class LocaleTest {
val connection = PostgresConnection("localhost:5432/test", user = "test", password = "test")
val table = connection.getTable(name = "locale_test") { LocaleDao() }

init {
table.recreate()

table.insert(LocaleDao(locale = Locale.GERMAN))

connection.driver.setSqlLogger(ConsoleSqlLogger)
}

@Test
fun selectAll() {
assertEquals(Locale.GERMAN, table.select<Locale>(property("locale")).first())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import com.google.gson.ToNumberStrategy
import de.mineking.database.*
import org.jdbi.v3.core.argument.Argument
import org.jdbi.v3.core.statement.StatementContext
import java.awt.Color
import java.io.ByteArrayInputStream
import java.io.ByteArrayOutputStream
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.sql.*
import java.sql.Date
import java.time.Instant
import java.time.LocalDate
import java.time.LocalDateTime
import java.util.*
import kotlin.reflect.KProperty
import kotlin.reflect.KType
import kotlin.reflect.jvm.javaType
Expand Down Expand Up @@ -77,6 +80,9 @@ object SQLiteMappers {
val LOCAL_DATE_TIME = typeMapper<LocalDateTime?>(SQLiteType.INTEGER, { set, name -> set.getTimestamp(name).toLocalDateTime() }, { value, statement, position -> statement.setTimestamp(position, value?.let { Timestamp.valueOf(it) }) })
val LOCAL_DATE = typeMapper<LocalDate?>(SQLiteType.INTEGER, { set, name -> set.getDate(name).toLocalDate() }, { value, statement, position -> statement.setDate(position, value?.let { Date.valueOf(it) }) })

val LOCALE = typeMapper(STRING, { it?.let { Locale.forLanguageTag(it) } }, { it?.toLanguageTag() })
val COLOR = typeMapper(INTEGER, { it?.let { Color(it, true) } }, { it?.rgb })

val ARRAY = object : TypeMapper<Any?, ByteArray> {
fun Any.asArray(): Array<*> = when (this) {
is Array<*> -> this
Expand Down
32 changes: 32 additions & 0 deletions sqlite/src/test/kotlin/tests/sqlite/specific/Color.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package tests.sqlite.specific

import de.mineking.database.*
import de.mineking.database.vendors.sqlite.SQLiteConnection
import org.junit.jupiter.api.Test
import setup.ConsoleSqlLogger
import setup.recreate
import java.awt.Color
import kotlin.test.assertEquals

data class ColorDao(
@AutoIncrement @Key @Column val id: Int = 0,
@Column val color: Color = Color.WHITE
)

class ColorTest {
val connection = SQLiteConnection("test.db")
val table = connection.getTable(name = "color_test") { ColorDao() }

init {
table.recreate()

table.insert(ColorDao(color = Color.GREEN))

connection.driver.setSqlLogger(ConsoleSqlLogger)
}

@Test
fun selectAll() {
assertEquals(Color.GREEN, table.select<Color>(property("color")).first())
}
}
32 changes: 32 additions & 0 deletions sqlite/src/test/kotlin/tests/sqlite/specific/Locale.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package tests.sqlite.specific

import de.mineking.database.*
import de.mineking.database.vendors.sqlite.SQLiteConnection
import org.junit.jupiter.api.Test
import setup.ConsoleSqlLogger
import setup.recreate
import java.util.*
import kotlin.test.assertEquals

data class LocaleDao(
@AutoIncrement @Key @Column val id: Int = 0,
@Column val locale: Locale = Locale.ENGLISH,
)

class LocaleTest {
val connection = SQLiteConnection("test.db")
val table = connection.getTable(name = "locale_test") { LocaleDao() }

init {
table.recreate()

table.insert(LocaleDao(locale = Locale.GERMAN))

connection.driver.setSqlLogger(ConsoleSqlLogger)
}

@Test
fun selectAll() {
assertEquals(Locale.GERMAN, table.select<Locale>(property("locale")).first())
}
}

0 comments on commit 256939e

Please sign in to comment.