Removes sqlite-jdbc in favor of SQLDelight.
This commit is contained in:
parent
69a43e6252
commit
b4f2f51032
5 changed files with 320 additions and 344 deletions
|
@ -11,7 +11,7 @@ plugins {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("app.cash.sqldelight:sqlite-driver:2.0.2")
|
implementation("app.cash.sqldelight:sqlite-driver:2.0.2")
|
||||||
implementation("org.xerial:sqlite-jdbc:3.48.0.0")
|
// implementation("org.xerial:sqlite-jdbc:3.48.0.0")
|
||||||
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
|
implementation("com.fasterxml.jackson.core:jackson-databind:2.18.2")
|
||||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.+")
|
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.18.+")
|
||||||
implementation(libs.slf4jsimple)
|
implementation(libs.slf4jsimple)
|
||||||
|
@ -24,7 +24,7 @@ dependencies {
|
||||||
application {
|
application {
|
||||||
// Define the Fully Qualified Name for the application main class
|
// Define the Fully Qualified Name for the application main class
|
||||||
// (Note that Kotlin compiles `App.kt` to a class with FQN `com.example.app.AppKt`.)
|
// (Note that Kotlin compiles `App.kt` to a class with FQN `com.example.app.AppKt`.)
|
||||||
mainClass = "net.h34t.app.AppKt"
|
mainClass = "net.h34t.filemure.ServerKt"
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import io.javalin.http.Context
|
||||||
import io.javalin.http.ForbiddenResponse
|
import io.javalin.http.ForbiddenResponse
|
||||||
import io.javalin.http.Header
|
import io.javalin.http.Header
|
||||||
import net.h34t.filemure.*
|
import net.h34t.filemure.*
|
||||||
|
import net.h34t.filemure.core.entity.State
|
||||||
import net.h34t.filemure.core.entity.Tag
|
import net.h34t.filemure.core.entity.Tag
|
||||||
import net.h34t.filemure.repository.SqliteRepository
|
import net.h34t.filemure.repository.SqliteRepository
|
||||||
import net.h34t.filemure.tpl.*
|
import net.h34t.filemure.tpl.*
|
||||||
|
@ -20,9 +21,9 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
|
||||||
|
|
||||||
fun documentDetail(ctx: Context) {
|
fun documentDetail(ctx: Context) {
|
||||||
val session = ctx.requireSession()
|
val session = ctx.requireSession()
|
||||||
val extId = ctx.pathParam("extId")
|
val extId = ExtId(ctx.pathParam("extId"))
|
||||||
|
|
||||||
val document = repository.getDocumentByExtId(accountId = session.id, extId = extId)
|
val document = repository.getDocumentByExtId(accountId = session.id, extId = extId, state = State.ACTIVE)
|
||||||
|
|
||||||
ctx.tempolin(
|
ctx.tempolin(
|
||||||
Frame(
|
Frame(
|
||||||
|
@ -121,7 +122,14 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
|
||||||
?: throw BadRequestResponse("")
|
?: throw BadRequestResponse("")
|
||||||
val fileExtIds = ctx.formParams("file_id")
|
val fileExtIds = ctx.formParams("file_id")
|
||||||
|
|
||||||
val extId = repository.addDocument(session.id, title, referenceDate, tags, description, fileExtIds)
|
val extId =
|
||||||
|
repository.addDocument(
|
||||||
|
session.id,
|
||||||
|
title,
|
||||||
|
referenceDate,
|
||||||
|
tags.map { Tag(it) },
|
||||||
|
description,
|
||||||
|
fileExtIds.map { ExtId(it) })
|
||||||
|
|
||||||
ctx.redirectPRG("/document/$extId")
|
ctx.redirectPRG("/document/$extId")
|
||||||
}
|
}
|
||||||
|
@ -134,7 +142,7 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
|
||||||
val session = ctx.requireSession()
|
val session = ctx.requireSession()
|
||||||
val extId = ctx.pathParam("extId")
|
val extId = ctx.pathParam("extId")
|
||||||
|
|
||||||
val file = repository.loadFile(accountId = session.id, extId = extId)
|
val file = repository.loadFile(accountId = session.id, extId = ExtId(extId))
|
||||||
|
|
||||||
file.contentType?.also { ctx.header(Header.CONTENT_TYPE, it) }
|
file.contentType?.also { ctx.header(Header.CONTENT_TYPE, it) }
|
||||||
ctx.result(file.content)
|
ctx.result(file.content)
|
||||||
|
@ -144,7 +152,7 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
|
||||||
val session = ctx.requireSession()
|
val session = ctx.requireSession()
|
||||||
val extId = ctx.pathParam("extId")
|
val extId = ctx.pathParam("extId")
|
||||||
|
|
||||||
val document = repository.getDocumentByExtId(accountId = session.id, extId = extId)
|
val document = repository.getDocumentByExtId(accountId = session.id, extId = ExtId(extId), state = State.ACTIVE)
|
||||||
|
|
||||||
ctx.tempolin(
|
ctx.tempolin(
|
||||||
Frame(
|
Frame(
|
||||||
|
@ -183,8 +191,11 @@ class DocumentController(val modifiers: TemplateModifiers, val repository: Sqlit
|
||||||
val session = ctx.requireSession()
|
val session = ctx.requireSession()
|
||||||
val extId = ctx.pathParam("extId")
|
val extId = ctx.pathParam("extId")
|
||||||
|
|
||||||
val document = repository.getDocumentByExtId(accountId = session.id, extId = extId)
|
val document = repository.getDocumentByExtId(
|
||||||
|
accountId = session.id,
|
||||||
|
extId = ExtId(extId),
|
||||||
|
state = State.ACTIVE
|
||||||
|
)
|
||||||
|
|
||||||
val title = ctx.formParam("title")
|
val title = ctx.formParam("title")
|
||||||
val referenceDate = ctx.formParam("reference_date")
|
val referenceDate = ctx.formParam("reference_date")
|
||||||
|
|
|
@ -1,92 +1,62 @@
|
||||||
package net.h34t.filemure.repository
|
package net.h34t.filemure.repository
|
||||||
|
|
||||||
|
import app.cash.sqldelight.db.SqlDriver
|
||||||
|
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
|
||||||
import net.h34t.filemure.ExtId
|
import net.h34t.filemure.ExtId
|
||||||
import net.h34t.filemure.core.entity.*
|
import net.h34t.filemure.core.entity.*
|
||||||
import net.h34t.filemure.core.entity.Tag.Companion.serialize
|
import net.h34t.filemure.core.entity.Tag.Companion.serialize
|
||||||
|
import net.h34t.filemure.db.Database
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.sql.Connection
|
|
||||||
import java.sql.DriverManager
|
|
||||||
import java.time.LocalDateTime
|
import java.time.LocalDateTime
|
||||||
import java.time.format.DateTimeFormatter
|
import java.time.format.DateTimeFormatter
|
||||||
|
|
||||||
class SqliteRepository(url: String) {
|
class SqliteRepository(url: String) {
|
||||||
|
|
||||||
private val dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
private val sqliteDtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||||
|
|
||||||
val connection: Connection = DriverManager.getConnection(url)
|
// private val connection: Connection = DriverManager.getConnection(url)
|
||||||
|
private val database: Database
|
||||||
|
|
||||||
|
init {
|
||||||
|
val driver: SqlDriver = JdbcSqliteDriver("jdbc:sqlite:test.db")
|
||||||
|
Database.Schema.create(driver)
|
||||||
|
database = Database(driver)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun toLDT(value: String) = LocalDateTime.parse(value, sqliteDtf)
|
||||||
|
|
||||||
fun addFileToLimbo(accountId: Long, filename: String, contentType: String?, size: Long, content: InputStream) {
|
fun addFileToLimbo(accountId: Long, filename: String, contentType: String?, size: Long, content: InputStream) {
|
||||||
connection.prepareStatement("INSERT INTO file (account_id, ext_id, filename, content_type, file_size, content) VALUES (?,?,?,?,?,?)")
|
database.databaseQueries.insertFileIntoLimbo(
|
||||||
.use { stmt ->
|
account_id = accountId,
|
||||||
stmt.setLong(1, accountId)
|
ext_id = ExtId.generate().value,
|
||||||
stmt.setString(2, ExtId.generate().toString())
|
filename = filename,
|
||||||
stmt.setString(3, filename)
|
content_type = contentType,
|
||||||
stmt.setString(4, contentType)
|
file_size = size,
|
||||||
stmt.setLong(5, size)
|
content = content.readAllBytes()
|
||||||
stmt.setBytes(6, content.readAllBytes())
|
|
||||||
|
|
||||||
val res = stmt.executeUpdate()
|
|
||||||
|
|
||||||
require(res == 1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLimboFileCount(accountId: Long, state: State = State.ACTIVE): Long {
|
|
||||||
connection.prepareStatement("SELECT count(*) AS count FROM file WHERE account_id=? AND document_id IS NULL AND state=?")
|
|
||||||
.use { stmt ->
|
|
||||||
stmt.setLong(1, accountId)
|
|
||||||
stmt.setInt(2, state.code)
|
|
||||||
val rs = stmt.executeQuery()
|
|
||||||
rs.next()
|
|
||||||
return rs.getLong(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getFilesInLimbo(accountId: Long, state: State = State.ACTIVE): List<FileRef> {
|
|
||||||
connection.prepareStatement(
|
|
||||||
"""
|
|
||||||
|SELECT
|
|
||||||
| id,
|
|
||||||
| ext_id,
|
|
||||||
| account_id,
|
|
||||||
| filename,
|
|
||||||
| content_type,
|
|
||||||
| content_extracted,
|
|
||||||
| file_size,
|
|
||||||
| created,
|
|
||||||
| state
|
|
||||||
|FROM
|
|
||||||
| file
|
|
||||||
|WHERE
|
|
||||||
| account_id=? AND
|
|
||||||
| document_id IS NULL
|
|
||||||
| AND state=?
|
|
||||||
|ORDER BY
|
|
||||||
| created DESC
|
|
||||||
""".trimMargin()
|
|
||||||
).use { stmt ->
|
|
||||||
stmt.setLong(1, accountId)
|
|
||||||
stmt.setInt(2, state.code)
|
|
||||||
val res = stmt.executeQuery()
|
|
||||||
|
|
||||||
val list = mutableListOf<FileRef>()
|
|
||||||
|
|
||||||
while (res.next()) {
|
|
||||||
list += FileRef(
|
|
||||||
id = res.getLong("id"),
|
|
||||||
extId = res.getString("ext_id"),
|
|
||||||
accountId = res.getLong("account_id"),
|
|
||||||
documentId = null,
|
|
||||||
filename = res.getString("filename"),
|
|
||||||
contentType = res.getString("content_type"),
|
|
||||||
contentExtracted = res.getString("content_extracted"),
|
|
||||||
fileSize = res.getLong("file_size"),
|
|
||||||
created = LocalDateTime.parse(res.getString("created"), dtf),
|
|
||||||
state = State.fromCode(res.getInt("state"))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return list
|
fun getLimboFileCount(accountId: Long, state: State = State.ACTIVE): Long {
|
||||||
|
return database.databaseQueries.getLimboFileCount(account_id = accountId, state = state.code.toLong())
|
||||||
|
.executeAsOne()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getFilesInLimbo(accountId: Long, state: State = State.ACTIVE): List<FileRef> {
|
||||||
|
return database.databaseQueries.getFilesInLimbo(account_id = accountId, state = state.code.toLong())
|
||||||
|
.executeAsList()
|
||||||
|
.map {
|
||||||
|
FileRef(
|
||||||
|
id = it.id,
|
||||||
|
accountId = it.account_id,
|
||||||
|
extId = it.ext_id,
|
||||||
|
documentId = null,
|
||||||
|
filename = it.filename,
|
||||||
|
fileSize = it.file_size,
|
||||||
|
contentType = it.content_type,
|
||||||
|
contentExtracted = it.content_extracted,
|
||||||
|
created = toLDT(it.created),
|
||||||
|
state = State.fromCode(it.state.toInt())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,97 +64,48 @@ class SqliteRepository(url: String) {
|
||||||
accountId: Long,
|
accountId: Long,
|
||||||
title: String,
|
title: String,
|
||||||
referenceDate: LocalDateTime,
|
referenceDate: LocalDateTime,
|
||||||
tags: List<String>,
|
tags: List<Tag>,
|
||||||
description: String,
|
description: String,
|
||||||
fileExtIds: List<String>
|
fileExtIds: List<ExtId>
|
||||||
): ExtId {
|
): ExtId {
|
||||||
|
|
||||||
val savePoint = connection.setSavepoint()
|
|
||||||
try {
|
|
||||||
val extId = ExtId.generate()
|
val extId = ExtId.generate()
|
||||||
|
database.databaseQueries.transaction {
|
||||||
|
database.databaseQueries.addDocument(
|
||||||
|
account_id = accountId,
|
||||||
|
ext_id = extId.value,
|
||||||
|
title = title,
|
||||||
|
description = description,
|
||||||
|
tags = tags.serialize(),
|
||||||
|
reference_date = referenceDate.format(sqliteDtf)
|
||||||
|
)
|
||||||
|
|
||||||
val documentId = connection.prepareStatement(
|
val documentId = database.databaseQueries.getLastInsertRowId().executeAsOne()
|
||||||
"""INSERT INTO document
|
|
||||||
|(account_id, ext_id, title, description, tags, created, reference_date)
|
database.databaseQueries.attachLimboFilesToDocument(
|
||||||
|VALUES
|
account_id = accountId,
|
||||||
|(?, ?, ?, ?, ?, datetime(), ?)""".trimMargin()
|
document_id = documentId,
|
||||||
).use { stmt ->
|
ext_id = fileExtIds.map { it.value }
|
||||||
stmt.setLong(1, accountId)
|
)
|
||||||
stmt.setString(2, extId.value)
|
|
||||||
stmt.setString(3, title)
|
|
||||||
stmt.setString(4, description)
|
|
||||||
stmt.setString(5, tags.joinToString(","))
|
|
||||||
stmt.setString(6, referenceDate.format(dtf))
|
|
||||||
stmt.executeUpdate()
|
|
||||||
val gks = stmt.generatedKeys
|
|
||||||
gks.next()
|
|
||||||
gks.getLong(1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val extIds = fileExtIds.joinToString(",") { "'$it'" }
|
return extId;
|
||||||
|
|
||||||
connection.prepareStatement("""UPDATE file SET document_id=? WHERE account_id=? AND ext_id IN ($extIds)""")
|
|
||||||
.use { stmt ->
|
|
||||||
stmt.setLong(1, documentId)
|
|
||||||
stmt.setLong(2, accountId)
|
|
||||||
val affected = stmt.executeUpdate()
|
|
||||||
require(affected == fileExtIds.size)
|
|
||||||
}
|
|
||||||
|
|
||||||
connection.commit()
|
|
||||||
return extId
|
|
||||||
} catch (exception: Exception) {
|
|
||||||
connection.rollback(savePoint)
|
|
||||||
throw exception
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getDocuments(accountId: Long, state: State = State.ACTIVE): List<Document> {
|
fun getDocuments(accountId: Long, state: State = State.ACTIVE): List<Document> {
|
||||||
connection.prepareStatement(
|
return database.databaseQueries.getDocuments(account_id = accountId, state = state.code.toLong())
|
||||||
"""
|
.executeAsList()
|
||||||
|SELECT
|
.map {
|
||||||
| d.id,
|
|
||||||
| d.account_id,
|
|
||||||
| d.ext_id,
|
|
||||||
| d.title,
|
|
||||||
| d.description,
|
|
||||||
| d.tags,
|
|
||||||
| d.created,
|
|
||||||
| d.reference_date,
|
|
||||||
| d.state
|
|
||||||
|FROM
|
|
||||||
| document d
|
|
||||||
|WHERE
|
|
||||||
| account_id=? AND
|
|
||||||
| state=?
|
|
||||||
""".trimMargin()
|
|
||||||
).use { stmt ->
|
|
||||||
stmt.setLong(1, accountId)
|
|
||||||
stmt.setInt(2, state.code)
|
|
||||||
val res = stmt.executeQuery()
|
|
||||||
|
|
||||||
val documentList = mutableListOf<Document>()
|
|
||||||
|
|
||||||
while (res.next()) {
|
|
||||||
documentList.add(
|
|
||||||
Document(
|
Document(
|
||||||
id = res.getLong("id"),
|
id = it.id,
|
||||||
extId = res.getString("ext_id"),
|
extId = it.ext_id,
|
||||||
title = res.getString("title"),
|
title = it.title,
|
||||||
description = res.getString("description"),
|
description = it.description,
|
||||||
tags = res.getString("tags")
|
tags = Tag.parse(it.tags),
|
||||||
?.let { if (it.isNotBlank()) it.split(",").map { tag -> Tag(tag) } else emptyList() }
|
created = toLDT(it.created),
|
||||||
?: emptyList(),
|
referenceDate = toLDT(it.reference_date),
|
||||||
created = LocalDateTime.parse(res.getString("created"), dtf),
|
state = State.fromCode(it.state.toInt()),
|
||||||
referenceDate = LocalDateTime.parse(res.getString("reference_date"), dtf),
|
|
||||||
state = State.fromCode(res.getInt("state")),
|
|
||||||
files = emptyList()
|
files = emptyList()
|
||||||
)
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return documentList.toList()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -197,144 +118,67 @@ class SqliteRepository(url: String) {
|
||||||
description: String,
|
description: String,
|
||||||
state: State = State.ACTIVE,
|
state: State = State.ACTIVE,
|
||||||
) {
|
) {
|
||||||
connection.prepareStatement(
|
database.databaseQueries.updateDocument(
|
||||||
"""
|
id = id,
|
||||||
|UPDATE
|
title = title,
|
||||||
| document
|
reference_date = referenceDate.format(sqliteDtf),
|
||||||
|SET
|
tags = tags.serialize(),
|
||||||
| title=?,
|
description = description,
|
||||||
| reference_date=?,
|
state = state.code.toLong(),
|
||||||
| tags=?,
|
account_id = accountId,
|
||||||
| description=?,
|
|
||||||
| state=?
|
|
||||||
|WHERE
|
|
||||||
| account_id=? AND
|
|
||||||
| id=?
|
|
||||||
""".trimMargin()
|
|
||||||
).use { stmt ->
|
|
||||||
stmt.setString(1, title)
|
|
||||||
stmt.setString(2, dtf.format(referenceDate))
|
|
||||||
stmt.setString(3, tags.serialize())
|
|
||||||
stmt.setString(4, description)
|
|
||||||
stmt.setInt(5, state.code)
|
|
||||||
stmt.setLong(6, accountId)
|
|
||||||
stmt.setLong(7, id)
|
|
||||||
|
|
||||||
stmt.executeUpdate()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getDocumentByExtId(accountId: Long, extId: String): Document {
|
|
||||||
return connection.prepareStatement(
|
|
||||||
"""
|
|
||||||
|SELECT
|
|
||||||
| d.id as d_id,
|
|
||||||
| d.account_id d_account_id,
|
|
||||||
| d.ext_id d_ext_id,
|
|
||||||
| d.title d_title,
|
|
||||||
| d.description d_description,
|
|
||||||
| d.tags d_tags,
|
|
||||||
| d.created d_created,
|
|
||||||
| d.reference_date d_reference_date,
|
|
||||||
| d.state as d_state,
|
|
||||||
| f.id f_id,
|
|
||||||
| f.ext_id f_ext_id,
|
|
||||||
| f.account_id f_account_id,
|
|
||||||
| f.document_id f_document_id,
|
|
||||||
| f.filename f_filename,
|
|
||||||
| f.content_type f_content_type,
|
|
||||||
| f.content_extracted f_content_extracted,
|
|
||||||
| f.file_size f_file_size,
|
|
||||||
| f.created f_created,
|
|
||||||
| f.state f_state
|
|
||||||
|FROM
|
|
||||||
| document d LEFT OUTER JOIN file f ON (d.id = f.document_id)
|
|
||||||
|WHERE
|
|
||||||
| d.ext_id=? AND
|
|
||||||
| d.account_id=?
|
|
||||||
""".trimMargin()
|
|
||||||
)
|
|
||||||
.use { stmt ->
|
|
||||||
|
|
||||||
|
|
||||||
stmt.setString(1, extId)
|
|
||||||
stmt.setLong(2, accountId)
|
|
||||||
val res = stmt.executeQuery()
|
|
||||||
var document: Document? = null
|
|
||||||
val files = mutableListOf<FileRef>()
|
|
||||||
|
|
||||||
while (res.next()) {
|
|
||||||
if (document == null) {
|
|
||||||
document = Document(
|
|
||||||
id = res.getLong("d_id"),
|
|
||||||
extId = res.getString("d_ext_id"),
|
|
||||||
title = res.getString("d_title"),
|
|
||||||
description = res.getString("d_description"),
|
|
||||||
tags = Tag.parse(res.getString("d_tags")),
|
|
||||||
created = LocalDateTime.parse(res.getString("d_created"), dtf),
|
|
||||||
referenceDate = LocalDateTime.parse(res.getString("d_reference_date"), dtf),
|
|
||||||
state = State.fromCode(res.getInt("d_state")),
|
|
||||||
files = emptyList()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val fid: Long = res.getLong("f_id")
|
fun getDocumentByExtId(accountId: Long, extId: ExtId, state: State): Document {
|
||||||
val wasNull = res.wasNull()
|
return database.databaseQueries.getDocumentByExtId(
|
||||||
|
account_id = accountId,
|
||||||
if (!wasNull) {
|
ext_id = extId.value,
|
||||||
files.add(
|
state = state.code.toLong()
|
||||||
|
).executeAsOne().let { d ->
|
||||||
|
Document(
|
||||||
|
id = d.id,
|
||||||
|
extId = d.ext_id,
|
||||||
|
title = d.title,
|
||||||
|
description = d.description,
|
||||||
|
tags = Tag.parse(d.tags),
|
||||||
|
created = toLDT(d.created),
|
||||||
|
referenceDate = toLDT(d.reference_date),
|
||||||
|
state = State.fromCode(d.state.toInt()),
|
||||||
|
files = database.databaseQueries.getFilesForDocument(
|
||||||
|
document_id = d.id,
|
||||||
|
account_id = accountId
|
||||||
|
).executeAsList().map { f ->
|
||||||
FileRef(
|
FileRef(
|
||||||
id = fid,
|
id = f.id,
|
||||||
extId = res.getString("f_ext_id"),
|
extId = f.ext_id,
|
||||||
accountId = res.getLong("f_account_id"),
|
accountId = f.account_id,
|
||||||
documentId = res.getLong("f_document_id"),
|
documentId = f.document_id,
|
||||||
filename = res.getString("f_filename"),
|
filename = f.filename,
|
||||||
contentType = res.getString("f_content_type"),
|
contentType = f.content_type,
|
||||||
contentExtracted = res.getString("f_content_extracted"),
|
contentExtracted = f.content_extracted,
|
||||||
fileSize = res.getLong("f_file_size"),
|
fileSize = f.file_size,
|
||||||
created = LocalDateTime.parse(res.getString("f_created"), dtf),
|
created = toLDT(f.created),
|
||||||
state = State.fromCode(res.getInt("f_state"))
|
state = State.fromCode(f.state.toInt())
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
requireNotNull(document)
|
|
||||||
document.copy(files = files)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun loadFile(accountId: Long, extId: String): FileContent {
|
fun loadFile(accountId: Long, extId: ExtId): FileContent {
|
||||||
return connection.prepareStatement(
|
return database
|
||||||
"""
|
.databaseQueries
|
||||||
|SELECT
|
.getFile(account_id = accountId, ext_id = extId.value)
|
||||||
| id,
|
.executeAsOne().let { f ->
|
||||||
| ext_id,
|
|
||||||
| filename,
|
|
||||||
| content_type,
|
|
||||||
| content_extracted,
|
|
||||||
| file_size,
|
|
||||||
| content
|
|
||||||
|FROM
|
|
||||||
| file
|
|
||||||
|WHERE
|
|
||||||
| account_id=? AND
|
|
||||||
| ext_id=?
|
|
||||||
""".trimMargin()
|
|
||||||
).use { stmt ->
|
|
||||||
stmt.setLong(1, accountId)
|
|
||||||
stmt.setString(2, extId)
|
|
||||||
val res = stmt.executeQuery()
|
|
||||||
|
|
||||||
FileContent(
|
FileContent(
|
||||||
id = res.getLong(1),
|
id = f.id,
|
||||||
extId = res.getString(2),
|
extId = f.ext_id,
|
||||||
filename = res.getString(3),
|
filename = f.filename,
|
||||||
contentType = res.getString(4),
|
contentType = f.content_type,
|
||||||
contentExtracted = res.getString(5),
|
contentExtracted = f.content_extracted,
|
||||||
fileSize = res.getLong(6),
|
fileSize = f.file_size,
|
||||||
content = res.getBytes(7)
|
content = f.content
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
-- account definition
|
|
||||||
|
|
||||||
CREATE TABLE account (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
email TEXT NOT NULL,
|
|
||||||
password TEXT NOT NULL,
|
|
||||||
created TEXT DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
|
|
||||||
state INTEGER DEFAULT (1) NOT NULL,
|
|
||||||
unique(email)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX account_state_IDX ON account (state);
|
|
||||||
|
|
||||||
|
|
||||||
-- document definition
|
|
||||||
|
|
||||||
CREATE TABLE document (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
account_id INTEGER NOT NULL,
|
|
||||||
ext_id TEXT NOT NULL,
|
|
||||||
title TEXT NOT NULL,
|
|
||||||
description TEXT NOT NULL,
|
|
||||||
tags TEXT NOT NULL,
|
|
||||||
created TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
|
||||||
reference_date TEXT, state INTEGER DEFAULT (1) NOT NULL,
|
|
||||||
CONSTRAINT document_account_FK FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE,
|
|
||||||
unique(ext_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX document_state_IDX ON document (state);
|
|
||||||
|
|
||||||
|
|
||||||
-- file definition
|
|
||||||
|
|
||||||
CREATE TABLE file (
|
|
||||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
|
||||||
account_id INTEGER NOT NULL,
|
|
||||||
document_id INTEGER DEFAULT null,
|
|
||||||
ext_id TEXT NOT NULL,
|
|
||||||
filename TEXT NOT NULL,
|
|
||||||
file_size INTEGER NOT NULL,
|
|
||||||
content BLOB NOT NULL,
|
|
||||||
content_type TEXT,
|
|
||||||
content_extracted TEXT,
|
|
||||||
created TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP, state INTEGER DEFAULT (1) NOT NULL,
|
|
||||||
CONSTRAINT file_account_FK FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE,
|
|
||||||
CONSTRAINT file_document_FK FOREIGN KEY (document_id) REFERENCES document(id) ON DELETE CASCADE,
|
|
||||||
unique(ext_id)
|
|
||||||
);
|
|
||||||
|
|
||||||
CREATE INDEX file_state_IDX ON file (state);
|
|
172
app/src/main/sqldelight/net/h34t/filemure/db/Database.sq
Normal file
172
app/src/main/sqldelight/net/h34t/filemure/db/Database.sq
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
-- account definition
|
||||||
|
|
||||||
|
CREATE TABLE account (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
email TEXT NOT NULL,
|
||||||
|
password TEXT NOT NULL,
|
||||||
|
created TEXT DEFAULT (CURRENT_TIMESTAMP) NOT NULL,
|
||||||
|
state INTEGER DEFAULT (1) NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX account_state_IDX ON account (state);
|
||||||
|
CREATE UNIQUE INDEX account_email_IDX ON account (email);
|
||||||
|
|
||||||
|
-- document definition
|
||||||
|
|
||||||
|
CREATE TABLE document (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
account_id INTEGER NOT NULL,
|
||||||
|
ext_id TEXT NOT NULL,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
description TEXT NOT NULL,
|
||||||
|
tags TEXT NOT NULL,
|
||||||
|
created TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
reference_date TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
state INTEGER NOT NULL DEFAULT (1),
|
||||||
|
CONSTRAINT document_account_FK FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX document_state_IDX ON document (state);
|
||||||
|
CREATE UNIQUE INDEX document_ext_id_IDX ON document (ext_id);
|
||||||
|
|
||||||
|
|
||||||
|
-- file definition
|
||||||
|
|
||||||
|
CREATE TABLE file (
|
||||||
|
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
account_id INTEGER NOT NULL,
|
||||||
|
document_id INTEGER DEFAULT NULL,
|
||||||
|
ext_id TEXT NOT NULL,
|
||||||
|
filename TEXT NOT NULL,
|
||||||
|
file_size INTEGER NOT NULL,
|
||||||
|
content BLOB NOT NULL,
|
||||||
|
content_type TEXT,
|
||||||
|
content_extracted TEXT,
|
||||||
|
created TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
state INTEGER NOT NULL DEFAULT (1),
|
||||||
|
CONSTRAINT file_account_FK FOREIGN KEY (account_id) REFERENCES account(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT file_document_FK FOREIGN KEY (document_id) REFERENCES document(id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX file_state_IDX ON file (state);
|
||||||
|
CREATE UNIQUE INDEX file_ext_id_IDX ON file (ext_id);
|
||||||
|
|
||||||
|
---
|
||||||
|
insertFileIntoLimbo:
|
||||||
|
INSERT INTO file (account_id, ext_id, filename, content_type, file_size, content) VALUES (?,?,?,?,?,?);
|
||||||
|
|
||||||
|
getLimboFileCount:
|
||||||
|
SELECT count(*) AS count FROM file WHERE account_id=? AND document_id IS NULL AND state=?;
|
||||||
|
|
||||||
|
getFilesInLimbo:
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
ext_id,
|
||||||
|
account_id,
|
||||||
|
filename,
|
||||||
|
content_type,
|
||||||
|
content_extracted,
|
||||||
|
file_size,
|
||||||
|
created,
|
||||||
|
state
|
||||||
|
FROM
|
||||||
|
file
|
||||||
|
WHERE
|
||||||
|
account_id=? AND
|
||||||
|
document_id IS NULL
|
||||||
|
AND state=?
|
||||||
|
ORDER BY
|
||||||
|
created DESC;
|
||||||
|
|
||||||
|
addDocument:
|
||||||
|
INSERT INTO document
|
||||||
|
(account_id, ext_id, title, description, tags, created, reference_date)
|
||||||
|
VALUES
|
||||||
|
(?, ?, ?, ?, ?, datetime(), ?);
|
||||||
|
|
||||||
|
attachLimboFilesToDocument:
|
||||||
|
UPDATE file SET document_id=? WHERE account_id=? AND ext_id IN ?;
|
||||||
|
|
||||||
|
getDocuments:
|
||||||
|
SELECT
|
||||||
|
d.id,
|
||||||
|
d.account_id,
|
||||||
|
d.ext_id,
|
||||||
|
d.title,
|
||||||
|
d.description,
|
||||||
|
d.tags,
|
||||||
|
d.created,
|
||||||
|
d.reference_date,
|
||||||
|
d.state
|
||||||
|
FROM
|
||||||
|
document d
|
||||||
|
WHERE
|
||||||
|
account_id=? AND
|
||||||
|
state=?;
|
||||||
|
|
||||||
|
updateDocument:
|
||||||
|
UPDATE
|
||||||
|
document
|
||||||
|
SET
|
||||||
|
title=?,
|
||||||
|
reference_date=?,
|
||||||
|
tags=?,
|
||||||
|
description=?,
|
||||||
|
state=?
|
||||||
|
WHERE
|
||||||
|
account_id=? AND
|
||||||
|
id=?;
|
||||||
|
|
||||||
|
getDocumentByExtId:
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
account_id,
|
||||||
|
ext_id,
|
||||||
|
title,
|
||||||
|
description,
|
||||||
|
tags,
|
||||||
|
created,
|
||||||
|
reference_date,
|
||||||
|
state
|
||||||
|
FROM
|
||||||
|
document d
|
||||||
|
WHERE
|
||||||
|
account_id=? AND
|
||||||
|
ext_id=? AND
|
||||||
|
state=?;
|
||||||
|
|
||||||
|
getFilesForDocument:
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
ext_id,
|
||||||
|
account_id,
|
||||||
|
document_id,
|
||||||
|
filename,
|
||||||
|
content_type,
|
||||||
|
content_extracted,
|
||||||
|
file_size,
|
||||||
|
created,
|
||||||
|
state
|
||||||
|
FROM
|
||||||
|
file
|
||||||
|
WHERE
|
||||||
|
document_id=? AND
|
||||||
|
account_id=?;
|
||||||
|
|
||||||
|
getFile:
|
||||||
|
SELECT
|
||||||
|
id,
|
||||||
|
ext_id,
|
||||||
|
filename,
|
||||||
|
content_type,
|
||||||
|
content_extracted,
|
||||||
|
file_size,
|
||||||
|
content
|
||||||
|
FROM
|
||||||
|
file
|
||||||
|
WHERE
|
||||||
|
account_id=? AND
|
||||||
|
ext_id=?;
|
||||||
|
|
||||||
|
getLastInsertRowId:
|
||||||
|
SELECT last_insert_rowid();
|
Loading…
Reference in a new issue