Dynamic column types

This commit is contained in:
Andrew Golovashevich 2024-12-04 18:27:10 +03:00
parent ac7df3393f
commit c223684442
4 changed files with 75 additions and 116 deletions

View File

@ -6,15 +6,15 @@ public interface Expression<RuntimeType, DatabaseType : ColumnType<RuntimeType>,
public interface Builder<OwnerBuilderUserExtension : Any> {
public fun <RuntimeType, DatabaseType : ColumnType<RuntimeType>> equals(
left: Expression<RuntimeType, DatabaseType, OwnerBuilderUserExtension>,
right: Expression<RuntimeType, DatabaseType, OwnerBuilderUserExtension>
right: Expression<RuntimeType, DatabaseType, OwnerBuilderUserExtension>,
): Expression<Boolean, ColumnType.BOOLEAN, OwnerBuilderUserExtension>
public fun isNull(
e: Expression<*, *, OwnerBuilderUserExtension>,
e: Expression<*, ColumnType.Nullable<*, *>, OwnerBuilderUserExtension>,
): Expression<Boolean, ColumnType.BOOLEAN, OwnerBuilderUserExtension>
public fun isNotNull(
e: Expression<*, *, OwnerBuilderUserExtension>,
e: Expression<*, ColumnType.Nullable<*, *>, OwnerBuilderUserExtension>,
): Expression<Boolean, ColumnType.BOOLEAN, OwnerBuilderUserExtension>
}
}

View File

@ -1,141 +1,96 @@
package ru.landgrafhomyak.serdha.api.v0.ddl
import kotlin.jvm.JvmStatic
import kotlin.jvm.JvmField
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.LocalTime
@Suppress("ClassName")
public abstract class ColumnType<RuntimeType> {
public abstract val typeName: String
@OptIn(ExperimentalUnsignedTypes::class)
@Suppress("ClassName", "RemoveRedundantQualifierName")
public interface ColumnType<@Suppress("unused") RuntimeType> {
public val typeName: String
abstract override fun toString(): String
@Suppress("FunctionName", "PropertyName")
public interface Builder {
public fun <TableUserExtension : Any> ROW_ID(): ColumnType<RowId<TableUserExtension>>
public sealed class _StandardType<R> : ColumnType<R>() {
override fun toString(): String = "<serdha | column type '${this.typeName}'>"
public val BOOLEAN: ColumnType.BOOLEAN
public val INT_S8: ColumnType.INT_S8
public val INT_U8: ColumnType.INT_U8
public val INT_S16: ColumnType.INT_S16
public val INT_U16: ColumnType.INT_U16
public val INT_S32: ColumnType.INT_S32
public val INT_U32: ColumnType.INT_U32
public val INT_S64: ColumnType.INT_S64
public val INT_U64: ColumnType.INT_U64
public val LOCAL_DATE: ColumnType.LOCAL_DATE
public val LOCAL_TIME: ColumnType.LOCAL_TIME
public val LOCAL_DATETIME: ColumnType.LOCAL_DATETIME
public val INSTANT: ColumnType.INSTANT
public val FLOAT_32: ColumnType.FLOAT_32
public val FLOAT_64: ColumnType.FLOAT_64
public val STRING: ColumnType.STRING
public fun STRING(size: UInt): ColumnType.STRING
public val BYTE_ARRAY: ColumnType.BYTE_ARRAY
public fun BYTE_ARRAY(size: UInt): ColumnType.BYTE_ARRAY
public fun <R : Any, D : ColumnType<R>> nullableOf(d: D): Nullable<R, D>
}
public abstract class _VirtualType<R>(@Suppress("MemberVisibilityCanBePrivate") public val wraps: ColumnType<R>) {
override fun toString(): String = "<serdha | virtual column type '${this.wraps.typeName}'>"
}
public abstract class _VirtualType<R : Any>(@Suppress("MemberVisibilityCanBePrivate") @JvmField public val wraps: ColumnType<R>)
public class NULLABLE<RuntimeType : Any>(@Suppress("MemberVisibilityCanBePrivate") public val notNullType: ColumnType<RuntimeType>) : _StandardType<RuntimeType?>() {
init {
if (this.notNullType is NULLABLE<*>)
throw IllegalArgumentException("Type can't be nullable twice")
}
public interface Nullable<R : Any, @Suppress("unused") D : ColumnType<R>> : ColumnType<R?>
override val typeName: String = this.notNullType.typeName + "?"
}
public interface ROW_ID : ColumnType<RowId<*>>
public object ROW_ID : _StandardType<RowId<*>>() {
override val typeName: String get() = "ROW_ID"
}
public interface BOOLEAN : ColumnType<Boolean>
public object BOOLEAN : _StandardType<Boolean>() {
override val typeName: String get() = "BOOLEAN"
}
public interface INT_S8 : ColumnType<Byte>
public object INT_S8 : _StandardType<Byte>() {
override val typeName: String get() = "INT_S8"
}
public interface INT_U8 : ColumnType<UByte>
public object INT_U8 : _StandardType<UByte>() {
override val typeName: String get() = "INT_U8"
}
public interface INT_S16 : ColumnType<Short>
public object INT_S16 : _StandardType<Short>() {
override val typeName: String get() = "INT_S16"
}
public interface INT_U16 : ColumnType<UShort>
public object INT_U16 : _StandardType<UShort>() {
override val typeName: String get() = "INT_U16"
}
public interface INT_S32 : ColumnType<Int>
public object INT_S32 : _StandardType<Int>() {
override val typeName: String get() = "INT_S32"
}
public interface INT_U32 : ColumnType<UInt>
public object INT_U32 : _StandardType<UInt>() {
override val typeName: String get() = "INT_U32"
}
public interface INT_S64 : ColumnType<Long>
public object INT_S64 : _StandardType<Long>() {
override val typeName: String get() = "INT_S64"
}
public interface INT_U64 : ColumnType<ULong>
public object INT_U64 : _StandardType<ULong>() {
override val typeName: String get() = "INT_U64"
}
public interface LOCAL_DATE : ColumnType<LocalDate>
public object LOCAL_DATE : _StandardType<LocalDate>() {
override val typeName: String get() = "LOCAL_DATE"
}
public interface LOCAL_TIME : ColumnType<LocalTime>
public object LOCAL_TIME : _StandardType<LocalTime>() {
override val typeName: String get() = "LOCAL_TIME"
}
public interface LOCAL_DATETIME : ColumnType<LocalDateTime>
public object LOCAL_DATETIME : _StandardType<LocalDateTime>() {
override val typeName: String get() = "LOCAL_DATETIME"
}
public interface INSTANT : ColumnType<Instant>
public object INSTANT : _StandardType<Instant>() {
override val typeName: String get() = "INSTANT"
}
public interface FLOAT_32 : ColumnType<Float>
public object FLOAT_32 : _StandardType<Float>() {
override val typeName: String get() = "FLOAT_32"
}
public interface FLOAT_64 : ColumnType<Double>
public object FLOAT_64 : _StandardType<Float>() {
override val typeName: String get() = "FLOAT_64"
}
public interface STRING : ColumnType<String>
public class STRING internal constructor(
private val _size: UInt
) : _StandardType<String>() {
override val typeName: String = if (this._size == 0u) "STRING" else "STRING(${this._size})"
public val size: UInt? get() = if (this._size == 0u) null else this._size
}
public class BYTE_ARRAY internal constructor(
private val _size: UInt
) : _StandardType<String>() {
override val typeName: String = if (this._size == 0u) "BYTE_ARRAY" else "BYTE_ARRAY(${this._size})"
public val size: UInt? get() = if (this._size == 0u) null else this._size
}
public companion object DSL {
@Suppress("RemoveRedundantQualifierName")
@JvmStatic
public val STRING: STRING = ColumnType.STRING(0u)
@Suppress("RemoveRedundantQualifierName")
@JvmStatic
public fun STRING(size: UInt): STRING {
if (size == 0u)
throw IllegalArgumentException("Size of string can't be 0")
return ColumnType.STRING(size)
}
@Suppress("RemoveRedundantQualifierName")
@JvmStatic
public val BYTE_ARRAY: BYTE_ARRAY = ColumnType.BYTE_ARRAY(0u)
@Suppress("RemoveRedundantQualifierName")
@JvmStatic
public fun BYTE_ARRAY(size: UInt): BYTE_ARRAY {
if (size == 0u)
throw IllegalArgumentException("Size of byte array can't be 0")
return ColumnType.BYTE_ARRAY(size)
}
@Suppress("FunctionName", "UNCHECKED_CAST", "RemoveRedundantQualifierName")
@JvmStatic
public fun <T : Any> ROW_ID(): ColumnType<RowId<T>> = ColumnType.ROW_ID as ColumnType<RowId<T>>
}
public interface BYTE_ARRAY : ColumnType<UByteArray>
}

View File

@ -6,6 +6,8 @@ import ru.landgrafhomyak.serdha.api.v0.Expression
public interface TableCreator<TableUserExtension : Any> {
public val expressionBuilder: Expression.Builder<TableUserExtension>
public val types: ColumnType.Builder
/**
* Offers column of type [D][type] with `NOT NULL` constraint named [name] and runtime type [RuntimeType].
*
@ -27,7 +29,7 @@ public interface TableCreator<TableUserExtension : Any> {
toTable: Table<TargetTableUserWrapper, *>,
toColumn: Column<*, ColumnType1, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction,
onDelete: ForeignKey.OnDeleteAction
onDelete: ForeignKey.OnDeleteAction,
): ForeignKey<TableUserExtension, TargetTableUserWrapper>
public fun <TargetTableUserWrapper : Any, ColumnType1 : ColumnType<*>, ColumnType2 : ColumnType<*>> foreignKey(
@ -37,7 +39,7 @@ public interface TableCreator<TableUserExtension : Any> {
toColumn1: Column<*, ColumnType1, TargetTableUserWrapper>,
toColumn2: Column<*, ColumnType2, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction,
onDelete: ForeignKey.OnDeleteAction
onDelete: ForeignKey.OnDeleteAction,
): ForeignKey<TableUserExtension, TargetTableUserWrapper>
public fun <TargetTableUserWrapper : Any, ColumnType1 : ColumnType<*>, ColumnType2 : ColumnType<*>, ColumnType3 : ColumnType<*>> foreignKey(
@ -49,6 +51,6 @@ public interface TableCreator<TableUserExtension : Any> {
toColumn2: Column<*, ColumnType2, TargetTableUserWrapper>,
toColumn3: Column<*, ColumnType3, TargetTableUserWrapper>,
onUpdate: ForeignKey.OnUpdateAction,
onDelete: ForeignKey.OnDeleteAction
onDelete: ForeignKey.OnDeleteAction,
): ForeignKey<TableUserExtension, TargetTableUserWrapper>
}

View File

@ -8,6 +8,8 @@ import ru.landgrafhomyak.serdha.api.v0.runtime.ParametersSetter
@Suppress("ClassName")
public interface _CommonQueryMethods<QueryUserExtension : Any> {
public val types: ColumnType.Builder
public fun <SelectedTableUserExtension : Any> selectTable(t: Table<SelectedTableUserExtension, *>): SelectedTable<SelectedTableUserExtension, QueryUserExtension>
public interface CanBeSubquery<@Suppress("unused") SelectedQueryUserExtension : Any>