Exposed based Table implementation #65
15
dataforge-exposed/build.gradle.kts
Normal file
15
dataforge-exposed/build.gradle.kts
Normal file
@ -0,0 +1,15 @@
|
||||
plugins {
|
||||
id("ru.mipt.npm.gradle.jvm")
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api("org.jetbrains.exposed:exposed-core:0.31.1")
|
||||
testImplementation("org.jetbrains.exposed:exposed-jdbc:0.31.1")
|
||||
testImplementation("com.h2database:h2:1.4.200")
|
||||
testImplementation("org.slf4j:slf4j-simple:1.7.30")
|
||||
api(project(":dataforge-tables"))
|
||||
}
|
||||
|
||||
readme {
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
package space.kscience.dataforge.exposed
|
||||
|
||||
import org.jetbrains.exposed.dao.id.EntityID
|
||||
import org.jetbrains.exposed.dao.id.IntIdTable
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.tables.Column
|
||||
import space.kscience.dataforge.tables.Row
|
||||
import space.kscience.dataforge.tables.Table
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
import org.jetbrains.exposed.sql.Column as SqlColumn
|
||||
|
||||
public class ExposedColumn<T : Any>(
|
||||
public val db: Database,
|
||||
public val sqlTable: IntIdTable,
|
||||
public val sqlColumn: SqlColumn<T>,
|
||||
public override val type: KType,
|
||||
) : Column<T> {
|
||||
public override val name: String
|
||||
get() = sqlColumn.name
|
||||
|
||||
public override val meta: Meta
|
||||
get() = Meta.EMPTY
|
||||
|
||||
public override val size: Int
|
||||
get() = transaction(db) { sqlColumn.table.selectAll().count().toInt() }
|
||||
|
||||
public override fun get(index: Int): T? = transaction(db) {
|
||||
sqlTable.select { sqlTable.id eq index + 1 }.firstOrNull()?.getOrNull(sqlColumn)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public class ExposedRow<T : Any>(
|
||||
public val db: Database,
|
||||
public val sqlTable: IntIdTable,
|
||||
public val sqlRow: ResultRow,
|
||||
) :
|
||||
Row<T> {
|
||||
public override fun get(column: String): T? = transaction(db) {
|
||||
val theColumn = sqlTable.columns.find { it.name == column } as SqlColumn<T>? ?: return@transaction null
|
||||
sqlRow.getOrNull(theColumn)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public class ExposedTable<T : Any>(public val db: Database, public val sqlTable: IntIdTable, public val type: KType) :
|
||||
Table<T> {
|
||||
public override val columns: List<Column<T>> =
|
||||
sqlTable.columns.filterNot { it.name == "id" }.map { ExposedColumn(db, sqlTable, it as SqlColumn<T>, type) }
|
||||
|
||||
public override val rows: List<Row<T>>
|
||||
get() = transaction(db) {
|
||||
sqlTable.selectAll().map { ExposedRow(db, sqlTable, it) }
|
||||
}
|
||||
|
||||
public override operator fun get(row: Int, column: String): T? = transaction(db) {
|
||||
val sqlColumn: SqlColumn<T> = sqlTable.columns.find { it.name == column } as SqlColumn<T>?
|
||||
?: return@transaction null
|
||||
|
||||
sqlTable.select { sqlTable.id eq row + 1 }.firstOrNull()?.getOrNull(sqlColumn)
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> ExposedTable(db: Database, table: IntIdTable): ExposedTable<T> =
|
||||
ExposedTable(db, table, typeOf<T>())
|
||||
|
||||
public inline fun <reified T : Any> ExposedTable(
|
||||
db: Database,
|
||||
tableName: String,
|
||||
columns: List<String>,
|
||||
sqlColumnType: IColumnType,
|
||||
): ExposedTable<T> {
|
||||
val table = object : IntIdTable(tableName) {
|
||||
init {
|
||||
columns.forEach { registerColumn<T>(it, sqlColumnType) }
|
||||
}
|
||||
}
|
||||
|
||||
transaction(db) { SchemaUtils.createMissingTablesAndColumns(table) }
|
||||
return ExposedTable(db, table)
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package space.kscience.dataforge.exposed
|
||||
|
||||
import org.jetbrains.exposed.sql.Column
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.IntegerColumnType
|
||||
import org.jetbrains.exposed.sql.insert
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
internal class ExposedTableTest {
|
||||
@Test
|
||||
fun exposedTable() {
|
||||
val db = Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")
|
||||
|
||||
val table = ExposedTable<Int>(
|
||||
db,
|
||||
"test",
|
||||
listOf("a", "b", "c"),
|
||||
IntegerColumnType(),
|
||||
)
|
||||
|
||||
transaction(db) {
|
||||
table.sqlTable.insert {
|
||||
it[table.sqlTable.columns.find { t -> t.name == "a" } as Column<Int>] = 42
|
||||
it[table.sqlTable.columns.find { t -> t.name == "b" } as Column<Int>] = 3
|
||||
it[table.sqlTable.columns.find { t -> t.name == "c" } as Column<Int>] = 7
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
assertEquals(42, table[0, "a"])
|
||||
assertEquals(3, table[0, "b"])
|
||||
assertEquals(7, table[0, "c"])
|
||||
assertEquals(3, table.columns.size)
|
||||
table.columns.forEach { assertEquals(1, it.size) }
|
||||
assertEquals(1, table.rows.size)
|
||||
}
|
||||
}
|
@ -27,5 +27,6 @@ include(
|
||||
// ":dataforge-output",
|
||||
":dataforge-tables",
|
||||
":dataforge-workspace",
|
||||
":dataforge-exposed",
|
||||
":dataforge-scripting"
|
||||
)
|
Loading…
Reference in New Issue
Block a user