Merge pull request #65 from CommanderTvis/commandertvis/table

Exposed based Table implementation
This commit is contained in:
Alexander Nozik 2021-05-09 09:28:29 +03:00 committed by GitHub
commit d769b0d389
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 140 additions and 0 deletions

View 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
}

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -27,5 +27,6 @@ include(
// ":dataforge-output",
":dataforge-tables",
":dataforge-workspace",
":dataforge-exposed",
":dataforge-scripting"
)