mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-23 19:08:26 +00:00
Temporary table support for holding fts results
This commit is contained in:
@ -13,6 +13,8 @@ import io.circe.{Decoder, Encoder}
|
||||
sealed trait Db {
|
||||
def name: String
|
||||
def driverClass: String
|
||||
|
||||
def fold[A](fpg: => A, fm: => A, fh2: => A): A
|
||||
}
|
||||
|
||||
object Db {
|
||||
@ -20,16 +22,19 @@ object Db {
|
||||
case object PostgreSQL extends Db {
|
||||
val name = "postgresql"
|
||||
val driverClass = "org.postgresql.Driver"
|
||||
def fold[A](fpg: => A, fm: => A, fh2: => A): A = fpg
|
||||
}
|
||||
|
||||
case object MariaDB extends Db {
|
||||
val name = "mariadb"
|
||||
val driverClass = "org.mariadb.jdbc.Driver"
|
||||
def fold[A](fpg: => A, fm: => A, fh2: => A): A = fm
|
||||
}
|
||||
|
||||
case object H2 extends Db {
|
||||
val name = "h2"
|
||||
val driverClass = "org.h2.Driver"
|
||||
def fold[A](fpg: => A, fm: => A, fh2: => A): A = fh2
|
||||
}
|
||||
|
||||
val all: NonEmptyList[Db] = NonEmptyList.of(PostgreSQL, MariaDB, H2)
|
||||
|
@ -36,6 +36,8 @@ trait Store[F[_]] {
|
||||
def add(insert: ConnectionIO[Int], exists: ConnectionIO[Boolean]): F[AddResult]
|
||||
|
||||
def transactor: Transactor[F]
|
||||
|
||||
def dbms: Db
|
||||
}
|
||||
|
||||
object Store {
|
||||
|
@ -29,6 +29,8 @@ final class StoreImpl[F[_]: Async](
|
||||
) extends Store[F] {
|
||||
private[this] val xa = transactor
|
||||
|
||||
val dbms = jdbc.dbms
|
||||
|
||||
def createFileRepository(
|
||||
cfg: FileRepositoryConfig,
|
||||
withAttributeStore: Boolean
|
||||
|
@ -0,0 +1,85 @@
|
||||
package docspell.store.impl
|
||||
|
||||
import cats.Foldable
|
||||
import cats.data.NonEmptyList
|
||||
import cats.effect._
|
||||
import cats.syntax.all._
|
||||
import docspell.common.Ident
|
||||
import docspell.store.Db
|
||||
import docspell.store.qb.{Column, TableDef}
|
||||
import docspell.store.impl.DoobieMeta._
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
/** Temporary table used to store item ids fetched from fulltext search */
|
||||
object TempIdTable {
|
||||
case class Row(id: Ident)
|
||||
case class Table(tableName: String, alias: Option[String], dbms: Db) extends TableDef {
|
||||
val id: Column[Ident] = Column("id", this)
|
||||
|
||||
val all: NonEmptyList[Column[_]] = NonEmptyList.of(id)
|
||||
|
||||
def as(newAlias: String): Table = copy(alias = Some(newAlias))
|
||||
|
||||
def insertAll[F[_]: Foldable](rows: F[Row]): ConnectionIO[Int] =
|
||||
insertBatch(this, rows)
|
||||
|
||||
def dropTable: ConnectionIO[Int] =
|
||||
TempIdTable.dropTable(Fragment.const0(tableName)).update.run
|
||||
|
||||
def createIndex: ConnectionIO[Unit] = {
|
||||
val analyze = dbms.fold(
|
||||
TempIdTable.analyzeTablePg(this),
|
||||
Sync[ConnectionIO].unit,
|
||||
Sync[ConnectionIO].unit
|
||||
)
|
||||
|
||||
TempIdTable.createIndex(this) *> analyze
|
||||
}
|
||||
}
|
||||
|
||||
def createTable(db: Db, name: String): ConnectionIO[Table] = {
|
||||
val stmt = db.fold(
|
||||
createTablePostgreSQL(Fragment.const(name)),
|
||||
createTableMariaDB(Fragment.const0(name)),
|
||||
createTableH2(Fragment.const0(name))
|
||||
)
|
||||
stmt.as(Table(name, None, db))
|
||||
}
|
||||
|
||||
private def dropTable(name: Fragment): Fragment =
|
||||
sql"""DROP TABLE IF EXISTS $name"""
|
||||
|
||||
private def createTableH2(name: Fragment): ConnectionIO[Int] =
|
||||
sql"""${dropTable(name)}; CREATE LOCAL TEMPORARY TABLE $name (
|
||||
| id varchar not null
|
||||
|);""".stripMargin.update.run
|
||||
|
||||
private def createTableMariaDB(name: Fragment): ConnectionIO[Int] =
|
||||
dropTable(name).update.run *>
|
||||
sql"CREATE TEMPORARY TABLE $name (id varchar(254) not null);".update.run
|
||||
|
||||
private def createTablePostgreSQL(name: Fragment): ConnectionIO[Int] =
|
||||
sql"""CREATE TEMPORARY TABLE IF NOT EXISTS $name (
|
||||
| id varchar not null
|
||||
|) ON COMMIT DROP;""".stripMargin.update.run
|
||||
|
||||
private def createIndex(table: Table): ConnectionIO[Unit] = {
|
||||
val idxName = Fragment.const0(s"${table.tableName}_id_idx")
|
||||
val tableName = Fragment.const0(table.tableName)
|
||||
val col = Fragment.const0(table.id.name)
|
||||
sql"""CREATE INDEX IF NOT EXISTS $idxName ON $tableName($col);""".update.run.void
|
||||
}
|
||||
|
||||
private def analyzeTablePg(table: Table): ConnectionIO[Unit] = {
|
||||
val tableName = Fragment.const0(table.tableName)
|
||||
sql"ANALYZE $tableName".update.run.void
|
||||
}
|
||||
|
||||
private def insertBatch[F[_]: Foldable](table: Table, rows: F[Row]) = {
|
||||
val sql =
|
||||
s"INSERT INTO ${table.tableName} (${table.id.name}) VALUES (?)"
|
||||
|
||||
Update[Row](sql).updateMany(rows)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user