ufoss-org / kotysa

The idiomatic way to write type-safe SQL in Kotlin
The Unlicense
116 stars 1 forks source link

Ability to define custom property types #100

Closed Metis-Adrastea closed 1 year ago

Metis-Adrastea commented 1 year ago

Hi, is there any possibility of extension for arbitrary property types? For example enums, BigDecimal, etc.

enum class Enum {
    ONE,
    TWO,
    THREE,
}

data class Example(
    val id: Int,
    val enum: Enum,
)

object Examples : PostgresqlTable<Example>("example") {
    val id = serial(Example::id).primaryKey()
    val scope = text(Example::enum)
}
pull-vert commented 1 year ago

Hello @Metis-Adrastea Right now Kotysa does not provide this feature, but here are 2 solutions based on a new String property enumAsText to map to your text database column

1) you can do like this, with 2 constructors : Kotysa will use the primary with the String property, in your code you can instantiate using the secondary that uses your Enum.

enum class Enum {
    ONE,
    TWO,
    THREE,
}

data class Example(
    val id: Int,
    val enumAsText: String,
) {
    constructor(fid: Int, enum: Enum) : this(id, enum.name)

    val enum: Enum
        get() = Enum.valueOf(enumAsText)
}

object Examples : PostgresqlTable<Example>("example") {
    val id = serial(Example::id).primaryKey()
    val scope = text(Example::enumAsText)
}

Or you can use the by operator, so you only have one constructor but you have to make your enum property a var in this case.

enum class Enum {
    ONE,
    TWO,
    THREE,
}

class TextValue(private var value: Enum) {
    operator fun getValue(
        thisRef: Any?,
        property: KProperty<*>
    ): String {
        return value.name
    }

    operator fun setValue(
        thisRef: Any?,
        property: KProperty<*>,
        value: String
    ) {
        this.value = Enum.valueOf(value)
    }
}

data class Example(
    val id: Int,
    var enum: Enum = Enum.ONE, // you need to make it a var with a default value
) {
    var enumAsText by TextValue(enum)
}

object Examples : PostgresqlTable<Example>("example") {
    val id = serial(Example::id).primaryKey()
    val scope = text(Example::enumAsText)
}
Metis-Adrastea commented 1 year ago

Hello @pull-vert ! Thank you so much!

pull-vert commented 1 year ago

Your welcome @Metis-Adrastea :wink: