mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-02-15 20:33:26 +00:00
Convert more records
This commit is contained in:
parent
613696539f
commit
fd6d09587d
@ -74,6 +74,10 @@ object DML {
|
||||
case Setter.Increment(column, amount) =>
|
||||
val colFrag = SelectExprBuilder.columnNoPrefix(column)
|
||||
colFrag ++ fr" =" ++ colFrag ++ fr" + $amount"
|
||||
|
||||
case Setter.Decrement(column, amount) =>
|
||||
val colFrag = SelectExprBuilder.columnNoPrefix(column)
|
||||
colFrag ++ fr" =" ++ colFrag ++ fr" - $amount"
|
||||
}
|
||||
|
||||
def set(s: Setter[_], more: Setter[_]*): Nel[Setter[_]] =
|
||||
|
@ -127,6 +127,9 @@ trait DSL extends DoobieMeta {
|
||||
def increment(amount: Int): Setter[A] =
|
||||
Setter.Increment(col, amount)
|
||||
|
||||
def decrement(amount: Int): Setter[A] =
|
||||
Setter.Decrement(col, amount)
|
||||
|
||||
def asc: OrderBy =
|
||||
OrderBy(SelectExpr.SelectColumn(col, None), OrderBy.OrderType.Asc)
|
||||
|
||||
@ -177,6 +180,9 @@ trait DSL extends DoobieMeta {
|
||||
|
||||
def ===(other: Column[A]): Condition =
|
||||
Condition.CompareCol(col, Operator.Eq, other)
|
||||
|
||||
def <>(other: Column[A]): Condition =
|
||||
Condition.CompareCol(col, Operator.Neq, other)
|
||||
}
|
||||
|
||||
implicit final class ConditionOps(c: Condition) {
|
||||
|
@ -13,5 +13,6 @@ object Setter {
|
||||
extends Setter[A]
|
||||
|
||||
case class Increment[A](column: Column[A], amount: Int) extends Setter[A]
|
||||
case class Decrement[A](column: Column[A], amount: Int) extends Setter[A]
|
||||
|
||||
}
|
||||
|
@ -180,14 +180,17 @@ object QAttachment {
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val iFolder = RItem.Columns.folder.prefix("i")
|
||||
val cId = RCollective.Columns.id.prefix("c")
|
||||
val cLang = RCollective.Columns.language.prefix("c")
|
||||
val c = RCollective.as("c")
|
||||
val cId = c.id.column
|
||||
val cLang = c.language.column
|
||||
|
||||
val cols = Seq(aId, aItem, iColl, iFolder, cLang, aName, mContent)
|
||||
val from = RAttachment.table ++ fr"a INNER JOIN" ++
|
||||
RAttachmentMeta.table ++ fr"m ON" ++ aId.is(mId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem) ++
|
||||
fr"INNER JOIN" ++ RCollective.table ++ fr"c ON" ++ cId.is(iColl)
|
||||
fr"INNER JOIN" ++ Fragment.const(RCollective.T.tableName) ++ fr"c ON" ++ cId.is(
|
||||
iColl
|
||||
)
|
||||
|
||||
val where = coll.map(cid => iColl.is(cid)).getOrElse(Fragment.empty)
|
||||
|
||||
|
@ -633,27 +633,31 @@ object QItem {
|
||||
limit: Option[Int],
|
||||
states: Set[ItemState]
|
||||
): Fragment = {
|
||||
val IC = RItem.Columns.all.map(_.prefix("i"))
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aFileId = RAttachment.Columns.fileId.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iState = RItem.Columns.state.prefix("i")
|
||||
val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
val sFileId = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
val rId = RAttachmentArchive.Columns.id.prefix("r")
|
||||
val rFileId = RAttachmentArchive.Columns.fileId.prefix("r")
|
||||
val m1Id = RFileMeta.Columns.id.prefix("m1")
|
||||
val m2Id = RFileMeta.Columns.id.prefix("m2")
|
||||
val m3Id = RFileMeta.Columns.id.prefix("m3")
|
||||
val IC = RItem.Columns.all.map(_.prefix("i"))
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aFileId = RAttachment.Columns.fileId.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iState = RItem.Columns.state.prefix("i")
|
||||
val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
val sFileId = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
val rId = RAttachmentArchive.Columns.id.prefix("r")
|
||||
val rFileId = RAttachmentArchive.Columns.fileId.prefix("r")
|
||||
val m1 = RFileMeta.as("m1")
|
||||
val m2 = RFileMeta.as("m2")
|
||||
val m3 = RFileMeta.as("m3")
|
||||
val m1Id = m1.id.column
|
||||
val m2Id = m2.id.column
|
||||
val m3Id = m3.id.column
|
||||
val filemetaTable = Fragment.const(RFileMeta.T.tableName)
|
||||
|
||||
val from =
|
||||
RItem.table ++ fr"i INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ aItem.is(iId) ++
|
||||
fr"INNER JOIN" ++ RAttachmentSource.table ++ fr"s ON" ++ aId.is(sId) ++
|
||||
fr"INNER JOIN" ++ RFileMeta.table ++ fr"m1 ON" ++ m1Id.is(aFileId) ++
|
||||
fr"INNER JOIN" ++ RFileMeta.table ++ fr"m2 ON" ++ m2Id.is(sFileId) ++
|
||||
fr"INNER JOIN" ++ filemetaTable ++ fr"m1 ON" ++ m1Id.is(aFileId) ++
|
||||
fr"INNER JOIN" ++ filemetaTable ++ fr"m2 ON" ++ m2Id.is(sFileId) ++
|
||||
fr"LEFT OUTER JOIN" ++ RAttachmentArchive.table ++ fr"r ON" ++ aId.is(rId) ++
|
||||
fr"LEFT OUTER JOIN" ++ RFileMeta.table ++ fr"m3 ON" ++ m3Id.is(rFileId)
|
||||
fr"LEFT OUTER JOIN" ++ filemetaTable ++ fr"m3 ON" ++ m3Id.is(rFileId)
|
||||
|
||||
val fileCond =
|
||||
or(m1Id.isIn(fileMetaIds), m2Id.isIn(fileMetaIds), m3Id.isIn(fileMetaIds))
|
||||
@ -691,30 +695,33 @@ object QItem {
|
||||
}
|
||||
|
||||
def findByChecksum(checksum: String, collective: Ident): ConnectionIO[Vector[RItem]] = {
|
||||
val IC = RItem.Columns.all.map(_.prefix("i"))
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aFileId = RAttachment.Columns.fileId.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
val sFileId = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
val rId = RAttachmentArchive.Columns.id.prefix("r")
|
||||
val rFileId = RAttachmentArchive.Columns.fileId.prefix("r")
|
||||
val m1Id = RFileMeta.Columns.id.prefix("m1")
|
||||
val m2Id = RFileMeta.Columns.id.prefix("m2")
|
||||
val m3Id = RFileMeta.Columns.id.prefix("m3")
|
||||
val m1Checksum = RFileMeta.Columns.checksum.prefix("m1")
|
||||
val m2Checksum = RFileMeta.Columns.checksum.prefix("m2")
|
||||
val m3Checksum = RFileMeta.Columns.checksum.prefix("m3")
|
||||
|
||||
val IC = RItem.Columns.all.map(_.prefix("i"))
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aFileId = RAttachment.Columns.fileId.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
val sFileId = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
val rId = RAttachmentArchive.Columns.id.prefix("r")
|
||||
val rFileId = RAttachmentArchive.Columns.fileId.prefix("r")
|
||||
val m1 = RFileMeta.as("m1")
|
||||
val m2 = RFileMeta.as("m2")
|
||||
val m3 = RFileMeta.as("m3")
|
||||
val m1Id = m1.id.column
|
||||
val m2Id = m2.id.column
|
||||
val m3Id = m3.id.column
|
||||
val m1Checksum = m1.checksum.column
|
||||
val m2Checksum = m2.checksum.column
|
||||
val m3Checksum = m3.checksum.column
|
||||
val filemetaTable = Fragment.const(RFileMeta.T.tableName)
|
||||
val from =
|
||||
RItem.table ++ fr"i INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ aItem.is(iId) ++
|
||||
fr"INNER JOIN" ++ RAttachmentSource.table ++ fr"s ON" ++ aId.is(sId) ++
|
||||
fr"INNER JOIN" ++ RFileMeta.table ++ fr"m1 ON" ++ m1Id.is(aFileId) ++
|
||||
fr"INNER JOIN" ++ RFileMeta.table ++ fr"m2 ON" ++ m2Id.is(sFileId) ++
|
||||
fr"INNER JOIN" ++ filemetaTable ++ fr"m1 ON" ++ m1Id.is(aFileId) ++
|
||||
fr"INNER JOIN" ++ filemetaTable ++ fr"m2 ON" ++ m2Id.is(sFileId) ++
|
||||
fr"LEFT OUTER JOIN" ++ RAttachmentArchive.table ++ fr"r ON" ++ aId.is(rId) ++
|
||||
fr"LEFT OUTER JOIN" ++ RFileMeta.table ++ fr"m3 ON" ++ m3Id.is(rFileId)
|
||||
fr"LEFT OUTER JOIN" ++ filemetaTable ++ fr"m3 ON" ++ m3Id.is(rFileId)
|
||||
|
||||
selectSimple(
|
||||
IC,
|
||||
|
@ -3,8 +3,8 @@ package docspell.store.queries
|
||||
import cats.data.OptionT
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.records.RCollective.{Columns => CC}
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
import docspell.store.records.{RCollective, RRememberMe, RUser}
|
||||
|
||||
import doobie._
|
||||
@ -22,20 +22,14 @@ object QLogin {
|
||||
)
|
||||
|
||||
def findUser(acc: AccountId): ConnectionIO[Option[Data]] = {
|
||||
val user = RUser.as("u")
|
||||
val ucid = user.cid.column
|
||||
val login = user.login.column
|
||||
val pass = user.password.column
|
||||
val ustate = user.state.column
|
||||
val cstate = CC.state.prefix("c")
|
||||
val ccid = CC.id.prefix("c")
|
||||
|
||||
val sql = selectSimple(
|
||||
List(ucid, login, pass, cstate, ustate),
|
||||
Fragment.const(user.tableName) ++ fr"u, " ++ RCollective.table ++ fr"c",
|
||||
and(ucid.is(ccid), login.is(acc.user), ucid.is(acc.collective))
|
||||
)
|
||||
|
||||
val user = RUser.as("u")
|
||||
val coll = RCollective.as("c")
|
||||
val sql =
|
||||
Select(
|
||||
select(user.cid, user.login, user.password, coll.state, user.state),
|
||||
from(user).innerJoin(coll, user.cid === coll.id),
|
||||
user.login === acc.user && user.cid === acc.collective
|
||||
).build
|
||||
logger.trace(s"SQL : $sql")
|
||||
sql.query[Data].option
|
||||
}
|
||||
|
@ -5,8 +5,9 @@ import cats.implicits._
|
||||
import fs2.Stream
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb.TableDef
|
||||
import docspell.store.qb._
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import doobie._
|
||||
@ -22,10 +23,27 @@ case class RAttachment(
|
||||
) {}
|
||||
|
||||
object RAttachment {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "attachment"
|
||||
|
||||
val id = Column[Ident]("attachid", this)
|
||||
val itemId = Column[Ident]("itemid", this)
|
||||
val fileId = Column[Ident]("filemetaid", this)
|
||||
val position = Column[Int]("position", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
val name = Column[String]("name", this)
|
||||
val all = NonEmptyList.of[Column[_]](id, itemId, fileId, position, created, name)
|
||||
}
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
val table = fr"attachment"
|
||||
|
||||
object Columns {
|
||||
import docspell.store.impl._
|
||||
|
||||
val id = Column("attachid")
|
||||
val itemId = Column("itemid")
|
||||
val fileId = Column("filemetaid")
|
||||
@ -34,32 +52,37 @@ object RAttachment {
|
||||
val name = Column("name")
|
||||
val all = List(id, itemId, fileId, position, created, name)
|
||||
}
|
||||
import Columns._
|
||||
|
||||
def insert(v: RAttachment): ConnectionIO[Int] =
|
||||
insertRow(
|
||||
table,
|
||||
all,
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${v.id},${v.itemId},${v.fileId.id},${v.position},${v.created},${v.name}"
|
||||
).update.run
|
||||
)
|
||||
|
||||
def decPositions(iId: Ident, lowerBound: Int, upperBound: Int): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
and(itemId.is(iId), position.isGte(lowerBound), position.isLte(upperBound)),
|
||||
position.decrement(1)
|
||||
).update.run
|
||||
DML.update(
|
||||
T,
|
||||
where(
|
||||
T.itemId === iId && T.position >= lowerBound && T.position <= upperBound
|
||||
),
|
||||
DML.set(T.position.decrement(1))
|
||||
)
|
||||
|
||||
def incPositions(iId: Ident, lowerBound: Int, upperBound: Int): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
and(itemId.is(iId), position.isGte(lowerBound), position.isLte(upperBound)),
|
||||
position.increment(1)
|
||||
).update.run
|
||||
DML.update(
|
||||
T,
|
||||
where(
|
||||
T.itemId === iId && T.position >= lowerBound && T.position <= upperBound
|
||||
),
|
||||
DML.set(T.position.increment(1))
|
||||
)
|
||||
|
||||
def nextPosition(id: Ident): ConnectionIO[Int] =
|
||||
for {
|
||||
max <- selectSimple(position.max, table, itemId.is(id)).query[Option[Int]].unique
|
||||
max <- Select(max(T.position).s, from(T), T.itemId === id).build
|
||||
.query[Option[Int]]
|
||||
.unique
|
||||
} yield max.map(_ + 1).getOrElse(0)
|
||||
|
||||
def updateFileIdAndName(
|
||||
@ -67,41 +90,49 @@ object RAttachment {
|
||||
fId: Ident,
|
||||
fname: Option[String]
|
||||
): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
id.is(attachId),
|
||||
commas(fileId.setTo(fId), name.setTo(fname))
|
||||
).update.run
|
||||
DML.update(
|
||||
T,
|
||||
T.id === attachId,
|
||||
DML.set(T.fileId.setTo(fId), T.name.setTo(fname))
|
||||
)
|
||||
|
||||
def updateFileId(
|
||||
attachId: Ident,
|
||||
fId: Ident
|
||||
): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
id.is(attachId),
|
||||
fileId.setTo(fId)
|
||||
).update.run
|
||||
DML.update(
|
||||
T,
|
||||
T.id === attachId,
|
||||
DML.set(T.fileId.setTo(fId))
|
||||
)
|
||||
|
||||
def updatePosition(attachId: Ident, pos: Int): ConnectionIO[Int] =
|
||||
updateRow(table, id.is(attachId), position.setTo(pos)).update.run
|
||||
DML.update(T, T.id === attachId, DML.set(T.position.setTo(pos)))
|
||||
|
||||
def findById(attachId: Ident): ConnectionIO[Option[RAttachment]] =
|
||||
selectSimple(all, table, id.is(attachId)).query[RAttachment].option
|
||||
run(select(T.all), from(T), T.id === attachId).query[RAttachment].option
|
||||
|
||||
def findMeta(attachId: Ident): ConnectionIO[Option[FileMeta]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
val cols = RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
val aId = id.prefix("a")
|
||||
val aFileMeta = fileId.prefix("a")
|
||||
val mId = RFileMeta.Columns.id.prefix("m")
|
||||
|
||||
val from =
|
||||
table ++ fr"a INNER JOIN" ++ RFileMeta.table ++ fr"m ON" ++ aFileMeta.is(mId)
|
||||
val cond = aId.is(attachId)
|
||||
|
||||
selectSimple(cols, from, cond).query[FileMeta].option
|
||||
// val cols = RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
// val aId = id.prefix("a")
|
||||
// val aFileMeta = fileId.prefix("a")
|
||||
// val mId = RFileMeta.Columns.id.prefix("m")
|
||||
//
|
||||
// val from =
|
||||
// table ++ fr"a INNER JOIN" ++ RFileMeta.table ++ fr"m ON" ++ aFileMeta.is(mId)
|
||||
// val cond = aId.is(attachId)
|
||||
//
|
||||
// selectSimple(cols, from, cond).query[FileMeta].option
|
||||
val m = RFileMeta.as("m")
|
||||
val a = RAttachment.as("a")
|
||||
Select(
|
||||
select(m.all),
|
||||
from(a)
|
||||
.innerJoin(m, a.fileId === m.id),
|
||||
a.id === attachId
|
||||
).build.query[FileMeta].option
|
||||
}
|
||||
|
||||
def updateName(
|
||||
@ -109,7 +140,7 @@ object RAttachment {
|
||||
collective: Ident,
|
||||
aname: Option[String]
|
||||
): ConnectionIO[Int] = {
|
||||
val update = updateRow(table, id.is(attachId), name.setTo(aname)).update.run
|
||||
val update = DML.update(T, T.id === attachId, DML.set(T.name.setTo(aname)))
|
||||
for {
|
||||
exists <- existsByIdAndCollective(attachId, collective)
|
||||
n <- if (exists) update else 0.pure[ConnectionIO]
|
||||
@ -119,44 +150,59 @@ object RAttachment {
|
||||
def findByIdAndCollective(
|
||||
attachId: Ident,
|
||||
collective: Ident
|
||||
): ConnectionIO[Option[RAttachment]] =
|
||||
selectSimple(
|
||||
all.map(_.prefix("a")),
|
||||
table ++ fr"a," ++ RItem.table ++ fr"i",
|
||||
and(
|
||||
fr"a.itemid = i.itemid",
|
||||
id.prefix("a").is(attachId),
|
||||
RItem.Columns.cid.prefix("i").is(collective)
|
||||
)
|
||||
).query[RAttachment].option
|
||||
): ConnectionIO[Option[RAttachment]] = {
|
||||
val a = RAttachment.as("a")
|
||||
val i = RItem.as("i")
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a).innerJoin(i, a.itemId === i.id),
|
||||
a.id === attachId && i.cid === collective
|
||||
).build.query[RAttachment].option
|
||||
}
|
||||
|
||||
def findByItem(id: Ident): ConnectionIO[Vector[RAttachment]] =
|
||||
selectSimple(all, table, itemId.is(id)).query[RAttachment].to[Vector]
|
||||
run(select(T.all), from(T), T.itemId === id).query[RAttachment].to[Vector]
|
||||
|
||||
def existsByIdAndCollective(
|
||||
attachId: Ident,
|
||||
collective: Ident
|
||||
): ConnectionIO[Boolean] = {
|
||||
val aId = id.prefix("a")
|
||||
val aItem = itemId.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val from =
|
||||
table ++ fr"a INNER JOIN" ++ RItem.table ++ fr"i ON" ++ aItem.is(iId)
|
||||
val cond = and(iColl.is(collective), aId.is(attachId))
|
||||
selectCount(id, from, cond).query[Int].unique.map(_ > 0)
|
||||
// val aId = id.prefix("a")
|
||||
// val aItem = itemId.prefix("a")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val from =
|
||||
// table ++ fr"a INNER JOIN" ++ RItem.table ++ fr"i ON" ++ aItem.is(iId)
|
||||
// val cond = and(iColl.is(collective), aId.is(attachId))
|
||||
// selectCount(id, from, cond).query[Int].unique.map(_ > 0)
|
||||
val a = RAttachment.as("a")
|
||||
val i = RItem.as("i")
|
||||
Select(
|
||||
count(a.id).s,
|
||||
from(a)
|
||||
.innerJoin(i, a.itemId === i.id),
|
||||
i.cid === collective && a.id === attachId
|
||||
).build.query[Int].unique.map(_ > 0)
|
||||
}
|
||||
|
||||
def findByItemAndCollective(
|
||||
id: Ident,
|
||||
coll: Ident
|
||||
): ConnectionIO[Vector[RAttachment]] = {
|
||||
val q = selectSimple(all.map(_.prefix("a")), table ++ fr"a", Fragment.empty) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ RItem.Columns.id
|
||||
.prefix("i")
|
||||
.is(itemId.prefix("a")) ++
|
||||
fr"WHERE" ++ and(itemId.prefix("a").is(id), RItem.Columns.cid.prefix("i").is(coll))
|
||||
q.query[RAttachment].to[Vector]
|
||||
// val q = selectSimple(all.map(_.prefix("a")), table ++ fr"a", Fragment.empty) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ RItem.Columns.id
|
||||
// .prefix("i")
|
||||
// .is(itemId.prefix("a")) ++
|
||||
// fr"WHERE" ++ and(itemId.prefix("a").is(id), RItem.Columns.cid.prefix("i").is(coll))
|
||||
// q.query[RAttachment].to[Vector]
|
||||
val a = RAttachment.as("a")
|
||||
val i = RItem.as("i")
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(i, i.id === a.itemId),
|
||||
a.itemId === id && i.cid === coll
|
||||
).build.query[RAttachment].to[Vector]
|
||||
}
|
||||
|
||||
def findByItemCollectiveSource(
|
||||
@ -165,28 +211,42 @@ object RAttachment {
|
||||
fileIds: NonEmptyList[Ident]
|
||||
): ConnectionIO[Vector[RAttachment]] = {
|
||||
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val aItem = Columns.itemId.prefix("a")
|
||||
val aId = Columns.id.prefix("a")
|
||||
val aFile = Columns.fileId.prefix("a")
|
||||
val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
val sFile = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
val rId = RAttachmentArchive.Columns.id.prefix("r")
|
||||
val rFile = RAttachmentArchive.Columns.fileId.prefix("r")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val aItem = Columns.itemId.prefix("a")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val aFile = Columns.fileId.prefix("a")
|
||||
// val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
// val sFile = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
// val rId = RAttachmentArchive.Columns.id.prefix("r")
|
||||
// val rFile = RAttachmentArchive.Columns.fileId.prefix("r")
|
||||
//
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RItem.table ++ fr"i ON" ++ iId.is(aItem) ++ fr"LEFT JOIN" ++
|
||||
// RAttachmentSource.table ++ fr"s ON" ++ sId.is(aId) ++ fr"LEFT JOIN" ++
|
||||
// RAttachmentArchive.table ++ fr"r ON" ++ rId.is(aId)
|
||||
//
|
||||
// val cond = and(
|
||||
// iId.is(id),
|
||||
// iColl.is(coll),
|
||||
// or(aFile.isIn(fileIds), sFile.isIn(fileIds), rFile.isIn(fileIds))
|
||||
// )
|
||||
//
|
||||
// selectSimple(all.map(_.prefix("a")), from, cond).query[RAttachment].to[Vector]
|
||||
val i = RItem.as("i")
|
||||
val a = RAttachment.as("a")
|
||||
val s = RAttachmentSource.as("s")
|
||||
val r = RAttachmentArchive.as("r")
|
||||
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RItem.table ++ fr"i ON" ++ iId.is(aItem) ++ fr"LEFT JOIN" ++
|
||||
RAttachmentSource.table ++ fr"s ON" ++ sId.is(aId) ++ fr"LEFT JOIN" ++
|
||||
RAttachmentArchive.table ++ fr"r ON" ++ rId.is(aId)
|
||||
|
||||
val cond = and(
|
||||
iId.is(id),
|
||||
iColl.is(coll),
|
||||
or(aFile.isIn(fileIds), sFile.isIn(fileIds), rFile.isIn(fileIds))
|
||||
)
|
||||
|
||||
selectSimple(all.map(_.prefix("a")), from, cond).query[RAttachment].to[Vector]
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(i, i.id === a.itemId)
|
||||
.leftJoin(s, s.id === a.id)
|
||||
.leftJoin(r, r.id === a.id),
|
||||
i.id === id && i.cid === coll &&
|
||||
(a.fileId.in(fileIds) || s.fileId.in(fileIds) || r.fileId.in(fileIds))
|
||||
).build.query[RAttachment].to[Vector]
|
||||
}
|
||||
|
||||
def findByItemAndCollectiveWithMeta(
|
||||
@ -195,27 +255,45 @@ object RAttachment {
|
||||
): ConnectionIO[Vector[(RAttachment, FileMeta)]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
val afileMeta = fileId.prefix("a")
|
||||
val aItem = itemId.prefix("a")
|
||||
val mId = RFileMeta.Columns.id.prefix("m")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
|
||||
val from =
|
||||
table ++ fr"a INNER JOIN" ++ RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ aItem.is(iId)
|
||||
val cond = Seq(aItem.is(id), iColl.is(coll))
|
||||
|
||||
selectSimple(cols, from, and(cond)).query[(RAttachment, FileMeta)].to[Vector]
|
||||
// val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
// val afileMeta = fileId.prefix("a")
|
||||
// val aItem = itemId.prefix("a")
|
||||
// val mId = RFileMeta.Columns.id.prefix("m")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val from =
|
||||
// table ++ fr"a INNER JOIN" ++ RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ aItem.is(iId)
|
||||
// val cond = Seq(aItem.is(id), iColl.is(coll))
|
||||
//
|
||||
// selectSimple(cols, from, and(cond)).query[(RAttachment, FileMeta)].to[Vector]
|
||||
val a = RAttachment.as("a")
|
||||
val m = RFileMeta.as("m")
|
||||
val i = RItem.as("i")
|
||||
Select(
|
||||
select(a.all, m.all),
|
||||
from(a)
|
||||
.innerJoin(m, a.fileId === m.id)
|
||||
.innerJoin(i, a.itemId === i.id),
|
||||
a.itemId === id && i.cid === coll
|
||||
).build.query[(RAttachment, FileMeta)].to[Vector]
|
||||
}
|
||||
|
||||
def findByItemWithMeta(id: Ident): ConnectionIO[Vector[(RAttachment, FileMeta)]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
val q =
|
||||
fr"SELECT a.*,m.* FROM" ++ table ++ fr"a, filemeta m WHERE a.filemetaid = m.id AND a.itemid = $id ORDER BY a.position ASC"
|
||||
q.query[(RAttachment, FileMeta)].to[Vector]
|
||||
// val q =
|
||||
// fr"SELECT a.*,m.* FROM" ++ table ++ fr"a, filzemeta m
|
||||
// WHERE a.filemetaid = m.id AND a.itemid = $id ORDER BY a.position ASC"
|
||||
val a = RAttachment.as("a")
|
||||
val m = RFileMeta.as("m")
|
||||
Select(
|
||||
select(a.all, m.all),
|
||||
from(a)
|
||||
.innerJoin(m, a.fileId === m.id),
|
||||
a.itemId === id
|
||||
).orderBy(a.position.asc).build.query[(RAttachment, FileMeta)].to[Vector]
|
||||
}
|
||||
|
||||
/** Deletes the attachment and its related source and meta records.
|
||||
@ -225,110 +303,159 @@ object RAttachment {
|
||||
n0 <- RAttachmentMeta.delete(attachId)
|
||||
n1 <- RAttachmentSource.delete(attachId)
|
||||
n2 <- RAttachmentPreview.delete(attachId)
|
||||
n3 <- deleteFrom(table, id.is(attachId)).update.run
|
||||
n3 <- DML.delete(T, T.id === attachId)
|
||||
} yield n0 + n1 + n2 + n3
|
||||
|
||||
def findItemId(attachId: Ident): ConnectionIO[Option[Ident]] =
|
||||
selectSimple(Seq(itemId), table, id.is(attachId)).query[Ident].option
|
||||
Select(T.itemId.s, from(T), T.id === attachId).build.query[Ident].option
|
||||
|
||||
def findAll(
|
||||
coll: Option[Ident],
|
||||
chunkSize: Int
|
||||
): Stream[ConnectionIO, RAttachment] = {
|
||||
val aItem = Columns.itemId.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
|
||||
val cols = all.map(_.prefix("a"))
|
||||
// val aItem = Columns.itemId.prefix("a")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val cols = all.map(_.prefix("a"))
|
||||
//
|
||||
// coll match {
|
||||
// case Some(cid) =>
|
||||
// val join = table ++ fr"a INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem)
|
||||
// val cond = iColl.is(cid)
|
||||
// selectSimple(cols, join, cond)
|
||||
// .query[RAttachment]
|
||||
// .streamWithChunkSize(chunkSize)
|
||||
// case None =>
|
||||
// selectSimple(cols, table, Fragment.empty)
|
||||
// .query[RAttachment]
|
||||
// .streamWithChunkSize(chunkSize)
|
||||
// }
|
||||
val a = RAttachment.as("a")
|
||||
val i = RItem.as("i")
|
||||
|
||||
coll match {
|
||||
case Some(cid) =>
|
||||
val join = table ++ fr"a INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem)
|
||||
val cond = iColl.is(cid)
|
||||
selectSimple(cols, join, cond)
|
||||
.query[RAttachment]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(i, i.id === a.itemId),
|
||||
i.cid === cid
|
||||
).build.query[RAttachment].streamWithChunkSize(chunkSize)
|
||||
case None =>
|
||||
selectSimple(cols, table, Fragment.empty)
|
||||
Select(select(a.all), from(a)).build
|
||||
.query[RAttachment]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
}
|
||||
}
|
||||
|
||||
def findAllWithoutPageCount(chunkSize: Int): Stream[ConnectionIO, RAttachment] = {
|
||||
val aId = Columns.id.prefix("a")
|
||||
val aCreated = Columns.created.prefix("a")
|
||||
val mId = RAttachmentMeta.Columns.id.prefix("m")
|
||||
val mPages = RAttachmentMeta.Columns.pages.prefix("m")
|
||||
|
||||
val cols = all.map(_.prefix("a"))
|
||||
val join = table ++ fr"a LEFT OUTER JOIN" ++
|
||||
RAttachmentMeta.table ++ fr"m ON" ++ aId.is(mId)
|
||||
val cond = mPages.isNull
|
||||
|
||||
(selectSimple(cols, join, cond) ++ orderBy(aCreated.desc))
|
||||
.query[RAttachment]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val aCreated = Columns.created.prefix("a")
|
||||
// val mId = RAttachmentMeta.Columns.id.prefix("m")
|
||||
// val mPages = RAttachmentMeta.Columns.pages.prefix("m")
|
||||
//
|
||||
// val cols = all.map(_.prefix("a"))
|
||||
// val join = table ++ fr"a LEFT OUTER JOIN" ++
|
||||
// RAttachmentMeta.table ++ fr"m ON" ++ aId.is(mId)
|
||||
// val cond = mPages.isNull
|
||||
//
|
||||
// (selectSimple(cols, join, cond) ++ orderBy(aCreated.desc))
|
||||
// .query[RAttachment]
|
||||
// .streamWithChunkSize(chunkSize)
|
||||
val a = RAttachment.as("a")
|
||||
val m = RAttachmentMeta.as("m")
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.leftJoin(m, a.id === m.id),
|
||||
m.pages.isNull
|
||||
).build.query[RAttachment].streamWithChunkSize(chunkSize)
|
||||
}
|
||||
|
||||
def findWithoutPreview(
|
||||
coll: Option[Ident],
|
||||
chunkSize: Int
|
||||
): Stream[ConnectionIO, RAttachment] = {
|
||||
val aId = Columns.id.prefix("a")
|
||||
val aItem = Columns.itemId.prefix("a")
|
||||
val aCreated = Columns.created.prefix("a")
|
||||
val pId = RAttachmentPreview.Columns.id.prefix("p")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val aItem = Columns.itemId.prefix("a")
|
||||
// val aCreated = Columns.created.prefix("a")
|
||||
// val pId = RAttachmentPreview.Columns.id.prefix("p")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val cols = all.map(_.prefix("a"))
|
||||
// val baseJoin =
|
||||
// table ++ fr"a LEFT OUTER JOIN" ++
|
||||
// RAttachmentPreview.table ++ fr"p ON" ++ pId.is(aId)
|
||||
//
|
||||
// val baseCond =
|
||||
// Seq(pId.isNull)
|
||||
//
|
||||
// coll match {
|
||||
// case Some(cid) =>
|
||||
// val join = baseJoin ++ fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem)
|
||||
// val cond = and(baseCond ++ Seq(iColl.is(cid)))
|
||||
// (selectSimple(cols, join, cond) ++ orderBy(aCreated.desc))
|
||||
// .query[RAttachment]
|
||||
// .streamWithChunkSize(chunkSize)
|
||||
// case None =>
|
||||
// (selectSimple(cols, baseJoin, and(baseCond)) ++ orderBy(aCreated.desc))
|
||||
// .query[RAttachment]
|
||||
// .streamWithChunkSize(chunkSize)
|
||||
// }
|
||||
val a = RAttachment.as("a")
|
||||
val p = RAttachmentPreview.as("p")
|
||||
val i = RItem.as("i")
|
||||
|
||||
val cols = all.map(_.prefix("a"))
|
||||
val baseJoin =
|
||||
table ++ fr"a LEFT OUTER JOIN" ++
|
||||
RAttachmentPreview.table ++ fr"p ON" ++ pId.is(aId)
|
||||
|
||||
val baseCond =
|
||||
Seq(pId.isNull)
|
||||
|
||||
coll match {
|
||||
case Some(cid) =>
|
||||
val join = baseJoin ++ fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem)
|
||||
val cond = and(baseCond ++ Seq(iColl.is(cid)))
|
||||
(selectSimple(cols, join, cond) ++ orderBy(aCreated.desc))
|
||||
.query[RAttachment]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
case None =>
|
||||
(selectSimple(cols, baseJoin, and(baseCond)) ++ orderBy(aCreated.desc))
|
||||
.query[RAttachment]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
}
|
||||
val baseJoin = from(a).leftJoin(p, p.id === a.id)
|
||||
Select(
|
||||
select(a.all),
|
||||
coll.map(_ => baseJoin.innerJoin(i, i.id === a.itemId)).getOrElse(baseJoin),
|
||||
p.id.isNull &&? coll.map(cid => i.cid === cid)
|
||||
).orderBy(a.created.asc).build.query[RAttachment].streamWithChunkSize(chunkSize)
|
||||
}
|
||||
|
||||
def findNonConvertedPdf(
|
||||
coll: Option[Ident],
|
||||
chunkSize: Int
|
||||
): Stream[ConnectionIO, RAttachment] = {
|
||||
val aId = Columns.id.prefix("a")
|
||||
val aItem = Columns.itemId.prefix("a")
|
||||
val aFile = Columns.fileId.prefix("a")
|
||||
val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
val sFile = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val mId = RFileMeta.Columns.id.prefix("m")
|
||||
val mType = RFileMeta.Columns.mimetype.prefix("m")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val aItem = Columns.itemId.prefix("a")
|
||||
// val aFile = Columns.fileId.prefix("a")
|
||||
// val sId = RAttachmentSource.Columns.id.prefix("s")
|
||||
// val sFile = RAttachmentSource.Columns.fileId.prefix("s")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val mId = RFileMeta.Columns.id.prefix("m")
|
||||
// val mType = RFileMeta.Columns.mimetype.prefix("m")
|
||||
val pdfType = "application/pdf%"
|
||||
//
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RAttachmentSource.table ++ fr"s ON" ++ sId.is(aId) ++ fr"INNER JOIN" ++
|
||||
// RItem.table ++ fr"i ON" ++ iId.is(aItem) ++ fr"INNER JOIN" ++
|
||||
// RFileMeta.table ++ fr"m ON" ++ aFile.is(mId)
|
||||
// val where = coll match {
|
||||
// case Some(cid) => and(iColl.is(cid), aFile.is(sFile), mType.lowerLike(pdfType))
|
||||
// case None => and(aFile.is(sFile), mType.lowerLike(pdfType))
|
||||
// }
|
||||
// selectSimple(all.map(_.prefix("a")), from, where)
|
||||
// .query[RAttachment]
|
||||
// .streamWithChunkSize(chunkSize)
|
||||
val a = RAttachment.as("a")
|
||||
val s = RAttachmentSource.as("s")
|
||||
val i = RItem.as("i")
|
||||
val m = RFileMeta.as("m")
|
||||
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RAttachmentSource.table ++ fr"s ON" ++ sId.is(aId) ++ fr"INNER JOIN" ++
|
||||
RItem.table ++ fr"i ON" ++ iId.is(aItem) ++ fr"INNER JOIN" ++
|
||||
RFileMeta.table ++ fr"m ON" ++ aFile.is(mId)
|
||||
val where = coll match {
|
||||
case Some(cid) => and(iColl.is(cid), aFile.is(sFile), mType.lowerLike(pdfType))
|
||||
case None => and(aFile.is(sFile), mType.lowerLike(pdfType))
|
||||
}
|
||||
selectSimple(all.map(_.prefix("a")), from, where)
|
||||
.query[RAttachment]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(s, s.id === a.id)
|
||||
.innerJoin(i, i.id === a.itemId)
|
||||
.innerJoin(m, m.id === a.fileId),
|
||||
a.fileId === s.fileId &&
|
||||
m.mimetype.likes(pdfType) &&?
|
||||
coll.map(cid => i.cid === cid)
|
||||
).build.query[RAttachment].streamWithChunkSize(chunkSize)
|
||||
}
|
||||
}
|
||||
|
@ -3,8 +3,9 @@ package docspell.store.records
|
||||
import cats.data.NonEmptyList
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb.TableDef
|
||||
import docspell.store.qb._
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import doobie._
|
||||
@ -22,10 +23,25 @@ case class RAttachmentArchive(
|
||||
)
|
||||
|
||||
object RAttachmentArchive {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "attachment_archive"
|
||||
|
||||
val id = Column[Ident]("id", this)
|
||||
val fileId = Column[Ident]("file_id", this)
|
||||
val name = Column[String]("filename", this)
|
||||
val messageId = Column[String]("message_id", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
|
||||
val all = NonEmptyList.of[Column[_]](id, fileId, name, messageId, created)
|
||||
}
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
val table = fr"attachment_archive"
|
||||
|
||||
object Columns {
|
||||
import docspell.store.impl._
|
||||
|
||||
val id = Column("id")
|
||||
val fileId = Column("file_id")
|
||||
val name = Column("filename")
|
||||
@ -35,64 +51,83 @@ object RAttachmentArchive {
|
||||
val all = List(id, fileId, name, messageId, created)
|
||||
}
|
||||
|
||||
import Columns._
|
||||
|
||||
def of(ra: RAttachment, mId: Option[String]): RAttachmentArchive =
|
||||
RAttachmentArchive(ra.id, ra.fileId, ra.name, mId, ra.created)
|
||||
|
||||
def insert(v: RAttachmentArchive): ConnectionIO[Int] =
|
||||
insertRow(
|
||||
table,
|
||||
all,
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${v.id},${v.fileId},${v.name},${v.messageId},${v.created}"
|
||||
).update.run
|
||||
)
|
||||
|
||||
def findById(attachId: Ident): ConnectionIO[Option[RAttachmentArchive]] =
|
||||
selectSimple(all, table, id.is(attachId)).query[RAttachmentArchive].option
|
||||
run(select(T.all), from(T), T.id === attachId).query[RAttachmentArchive].option
|
||||
|
||||
def delete(attachId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, id.is(attachId)).update.run
|
||||
DML.delete(T, T.id === attachId)
|
||||
|
||||
def deleteAll(fId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, fileId.is(fId)).update.run
|
||||
DML.delete(T, T.fileId === fId)
|
||||
|
||||
def findByIdAndCollective(
|
||||
attachId: Ident,
|
||||
collective: Ident
|
||||
): ConnectionIO[Option[RAttachmentArchive]] = {
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val aId = Columns.id.prefix("a")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
//
|
||||
// val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective))
|
||||
//
|
||||
// selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentArchive].option
|
||||
val b = RAttachment.as("b")
|
||||
val a = RAttachmentArchive.as("a")
|
||||
val i = RItem.as("i")
|
||||
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
|
||||
val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective))
|
||||
|
||||
selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentArchive].option
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(b, b.id === a.id)
|
||||
.innerJoin(i, i.id === b.itemId),
|
||||
a.id === attachId && b.id === attachId && i.cid === collective
|
||||
).build.query[RAttachmentArchive].option
|
||||
}
|
||||
|
||||
def findByMessageIdAndCollective(
|
||||
messageIds: NonEmptyList[String],
|
||||
collective: Ident
|
||||
): ConnectionIO[Vector[RAttachmentArchive]] = {
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val aMsgId = Columns.messageId.prefix("a")
|
||||
val aId = Columns.id.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
|
||||
val where = and(aMsgId.isIn(messageIds), iColl.is(collective))
|
||||
|
||||
selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentArchive].to[Vector]
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val aMsgId = Columns.messageId.prefix("a")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
//
|
||||
// val where = and(aMsgId.isIn(messageIds), iColl.is(collective))
|
||||
//
|
||||
// selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentArchive].to[Vector]
|
||||
val b = RAttachment.as("b")
|
||||
val a = RAttachmentArchive.as("a")
|
||||
val i = RItem.as("i")
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(b, b.id === a.id)
|
||||
.innerJoin(i, i.id === b.itemId),
|
||||
a.messageId.in(messageIds) && i.cid === collective
|
||||
).build.query[RAttachmentArchive].to[Vector]
|
||||
}
|
||||
|
||||
def findByItemWithMeta(
|
||||
@ -100,31 +135,49 @@ object RAttachmentArchive {
|
||||
): ConnectionIO[Vector[(RAttachmentArchive, FileMeta)]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
val aId = Columns.id.prefix("a")
|
||||
val afileMeta = fileId.prefix("a")
|
||||
val bPos = RAttachment.Columns.position.prefix("b")
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val mId = RFileMeta.Columns.id.prefix("m")
|
||||
|
||||
val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++ fr"INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId)
|
||||
val where = bItem.is(id)
|
||||
|
||||
(selectSimple(cols, from, where) ++ orderBy(bPos.asc))
|
||||
.query[(RAttachmentArchive, FileMeta)]
|
||||
.to[Vector]
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val afileMeta = fileId.prefix("a")
|
||||
// val bPos = RAttachment.Columns.position.prefix("b")
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val mId = RFileMeta.as("m").id.column
|
||||
//
|
||||
// val cols = all.map(_.prefix("a")) ++ RFileMeta.as("m").all.map(_.column).toList
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// Fragment.const(RFileMeta.T.tableName) ++ fr"m ON" ++ afileMeta.is(
|
||||
// mId
|
||||
// ) ++ fr"INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId)
|
||||
// val where = bItem.is(id)
|
||||
//
|
||||
// (selectSimple(cols, from, where) ++ orderBy(bPos.asc))
|
||||
// .query[(RAttachmentArchive, FileMeta)]
|
||||
// .to[Vector]
|
||||
val a = RAttachmentArchive.as("a")
|
||||
val b = RAttachment.as("b")
|
||||
val m = RFileMeta.as("m")
|
||||
Select(
|
||||
select(a.all, m.all),
|
||||
from(a)
|
||||
.innerJoin(m, a.fileId === m.id)
|
||||
.innerJoin(b, a.id === b.id),
|
||||
b.itemId === id
|
||||
).orderBy(b.position.asc).build.query[(RAttachmentArchive, FileMeta)].to[Vector]
|
||||
}
|
||||
|
||||
/** If the given attachment id has an associated archive, this returns
|
||||
* the number of all associated attachments. Returns 0 if there is
|
||||
* no archive for the given attachment.
|
||||
*/
|
||||
def countEntries(attachId: Ident): ConnectionIO[Int] = {
|
||||
val qFileId = selectSimple(Seq(fileId), table, id.is(attachId))
|
||||
val q = selectCount(id, table, fileId.isSubquery(qFileId))
|
||||
q.query[Int].unique
|
||||
}
|
||||
def countEntries(attachId: Ident): ConnectionIO[Int] =
|
||||
// val qFileId = selectSimple(Seq(fileId), table, id.is(attachId))
|
||||
// val q = selectCount(id, table, fileId.isSubquery(qFileId))
|
||||
// q.query[Int].unique
|
||||
Select(
|
||||
count(T.id).s,
|
||||
from(T),
|
||||
T.fileId.in(Select(T.fileId.s, from(T), T.id === attachId))
|
||||
).build.query[Int].unique
|
||||
//TODO this looks strange, can be simplified
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
@ -29,9 +30,25 @@ object RAttachmentMeta {
|
||||
def empty(attachId: Ident) =
|
||||
RAttachmentMeta(attachId, None, Nil, MetaProposalList.empty, None)
|
||||
|
||||
val table = fr"attachmentmeta"
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "attachmentmeta"
|
||||
|
||||
val id = Column[Ident]("attachid", this)
|
||||
val content = Column[String]("content", this)
|
||||
val nerlabels = Column[List[NerLabel]]("nerlabels", this)
|
||||
val proposals = Column[MetaProposalList]("itemproposals", this)
|
||||
val pages = Column[Int]("page_count", this)
|
||||
val all = NonEmptyList.of[Column[_]](id, content, nerlabels, proposals, pages)
|
||||
}
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
val table = fr"attachmentmeta"
|
||||
object Columns {
|
||||
import docspell.store.impl._
|
||||
|
||||
val id = Column("attachid")
|
||||
val content = Column("content")
|
||||
val nerlabels = Column("nerlabels")
|
||||
@ -39,23 +56,22 @@ object RAttachmentMeta {
|
||||
val pages = Column("page_count")
|
||||
val all = List(id, content, nerlabels, proposals, pages)
|
||||
}
|
||||
import Columns._
|
||||
|
||||
def insert(v: RAttachmentMeta): ConnectionIO[Int] =
|
||||
insertRow(
|
||||
table,
|
||||
all,
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${v.id},${v.content},${v.nerlabels},${v.proposals},${v.pages}"
|
||||
).update.run
|
||||
)
|
||||
|
||||
def exists(attachId: Ident): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, id.is(attachId)).query[Int].unique.map(_ > 0)
|
||||
Select(count(T.id).s, from(T), T.id === attachId).build.query[Int].unique.map(_ > 0)
|
||||
|
||||
def findById(attachId: Ident): ConnectionIO[Option[RAttachmentMeta]] =
|
||||
selectSimple(all, table, id.is(attachId)).query[RAttachmentMeta].option
|
||||
run(select(T.all), from(T), T.id === attachId).query[RAttachmentMeta].option
|
||||
|
||||
def findPageCountById(attachId: Ident): ConnectionIO[Option[Int]] =
|
||||
selectSimple(Seq(pages), table, id.is(attachId))
|
||||
Select(T.pages.s, from(T), T.id === attachId).build
|
||||
.query[Option[Int]]
|
||||
.option
|
||||
.map(_.flatten)
|
||||
@ -67,37 +83,37 @@ object RAttachmentMeta {
|
||||
} yield n1
|
||||
|
||||
def update(v: RAttachmentMeta): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
id.is(v.id),
|
||||
commas(
|
||||
content.setTo(v.content),
|
||||
nerlabels.setTo(v.nerlabels),
|
||||
proposals.setTo(v.proposals)
|
||||
DML.update(
|
||||
T,
|
||||
T.id === v.id,
|
||||
DML.set(
|
||||
T.content.setTo(v.content),
|
||||
T.nerlabels.setTo(v.nerlabels),
|
||||
T.proposals.setTo(v.proposals)
|
||||
)
|
||||
).update.run
|
||||
)
|
||||
|
||||
def updateLabels(mid: Ident, labels: List[NerLabel]): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
id.is(mid),
|
||||
commas(
|
||||
nerlabels.setTo(labels)
|
||||
DML.update(
|
||||
T,
|
||||
T.id === mid,
|
||||
DML.set(
|
||||
T.nerlabels.setTo(labels)
|
||||
)
|
||||
).update.run
|
||||
)
|
||||
|
||||
def updateProposals(mid: Ident, plist: MetaProposalList): ConnectionIO[Int] =
|
||||
updateRow(
|
||||
table,
|
||||
id.is(mid),
|
||||
commas(
|
||||
proposals.setTo(plist)
|
||||
DML.update(
|
||||
T,
|
||||
T.id === mid,
|
||||
DML.set(
|
||||
T.proposals.setTo(plist)
|
||||
)
|
||||
).update.run
|
||||
)
|
||||
|
||||
def updatePageCount(mid: Ident, pageCount: Option[Int]): ConnectionIO[Int] =
|
||||
updateRow(table, id.is(mid), pages.setTo(pageCount)).update.run
|
||||
DML.update(T, T.id === mid, DML.set(T.pages.setTo(pageCount)))
|
||||
|
||||
def delete(attachId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, id.is(attachId)).update.run
|
||||
DML.delete(T, T.id === attachId)
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import doobie._
|
||||
@ -19,10 +21,24 @@ case class RAttachmentPreview(
|
||||
)
|
||||
|
||||
object RAttachmentPreview {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "attachment_preview"
|
||||
|
||||
val id = Column[Ident]("id", this)
|
||||
val fileId = Column[Ident]("file_id", this)
|
||||
val name = Column[String]("filename", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
|
||||
val all = NonEmptyList.of[Column[_]](id, fileId, name, created)
|
||||
}
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
val table = fr"attachment_preview"
|
||||
|
||||
object Columns {
|
||||
import docspell.store.impl._
|
||||
val id = Column("id")
|
||||
val fileId = Column("file_id")
|
||||
val name = Column("filename")
|
||||
@ -31,67 +47,98 @@ object RAttachmentPreview {
|
||||
val all = List(id, fileId, name, created)
|
||||
}
|
||||
|
||||
import Columns._
|
||||
|
||||
def insert(v: RAttachmentPreview): ConnectionIO[Int] =
|
||||
insertRow(table, all, fr"${v.id},${v.fileId},${v.name},${v.created}").update.run
|
||||
DML.insert(T, T.all, fr"${v.id},${v.fileId},${v.name},${v.created}")
|
||||
|
||||
def findById(attachId: Ident): ConnectionIO[Option[RAttachmentPreview]] =
|
||||
selectSimple(all, table, id.is(attachId)).query[RAttachmentPreview].option
|
||||
run(select(T.all), from(T), T.id === attachId).query[RAttachmentPreview].option
|
||||
|
||||
def delete(attachId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, id.is(attachId)).update.run
|
||||
DML.delete(T, T.id === attachId)
|
||||
|
||||
def findByIdAndCollective(
|
||||
attachId: Ident,
|
||||
collective: Ident
|
||||
): ConnectionIO[Option[RAttachmentPreview]] = {
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val aId = Columns.id.prefix("a")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
//
|
||||
// val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective))
|
||||
//
|
||||
// selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentPreview].option
|
||||
val b = RAttachment.as("b")
|
||||
val a = RAttachmentPreview.as("a")
|
||||
val i = RItem.as("i")
|
||||
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
|
||||
val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective))
|
||||
|
||||
selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentPreview].option
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(b, a.id === b.id)
|
||||
.innerJoin(i, i.id === b.itemId),
|
||||
a.id === attachId && b.id === attachId && i.cid === collective
|
||||
).build.query[RAttachmentPreview].option
|
||||
}
|
||||
|
||||
def findByItem(itemId: Ident): ConnectionIO[Vector[RAttachmentPreview]] = {
|
||||
val sId = Columns.id.prefix("s")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
|
||||
val from = table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId)
|
||||
selectSimple(all.map(_.prefix("s")), from, aItem.is(itemId))
|
||||
.query[RAttachmentPreview]
|
||||
.to[Vector]
|
||||
// val sId = Columns.id.prefix("s")
|
||||
// val aId = RAttachment.Columns.id.prefix("a")
|
||||
// val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
//
|
||||
// val from = table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId)
|
||||
// selectSimple(all.map(_.prefix("s")), from, aItem.is(itemId))
|
||||
// .query[RAttachmentPreview]
|
||||
// .to[Vector]
|
||||
val s = RAttachmentPreview.as("s")
|
||||
val a = RAttachment.as("a")
|
||||
Select(
|
||||
select(s.all),
|
||||
from(s)
|
||||
.innerJoin(a, s.id === a.id),
|
||||
a.itemId === itemId
|
||||
).build.query[RAttachmentPreview].to[Vector]
|
||||
}
|
||||
|
||||
def findByItemAndCollective(
|
||||
itemId: Ident,
|
||||
coll: Ident
|
||||
): ConnectionIO[Option[RAttachmentPreview]] = {
|
||||
val sId = Columns.id.prefix("s")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aPos = RAttachment.Columns.position.prefix("a")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val sId = Columns.id.prefix("s")
|
||||
// val aId = RAttachment.Columns.id.prefix("a")
|
||||
// val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
// val aPos = RAttachment.Columns.position.prefix("a")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val from =
|
||||
// table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem)
|
||||
//
|
||||
// selectSimple(
|
||||
// all.map(_.prefix("s")) ++ List(aPos),
|
||||
// from,
|
||||
// and(aItem.is(itemId), iColl.is(coll))
|
||||
// )
|
||||
// .query[(RAttachmentPreview, Int)]
|
||||
// .to[Vector]
|
||||
// .map(_.sortBy(_._2).headOption.map(_._1))
|
||||
val s = RAttachmentPreview.as("s")
|
||||
val a = RAttachment.as("a")
|
||||
val i = RItem.as("i")
|
||||
|
||||
val from =
|
||||
table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ iId.is(aItem)
|
||||
|
||||
selectSimple(
|
||||
all.map(_.prefix("s")) ++ List(aPos),
|
||||
from,
|
||||
and(aItem.is(itemId), iColl.is(coll))
|
||||
)
|
||||
Select(
|
||||
select(s.all).append(a.position.s),
|
||||
from(s)
|
||||
.innerJoin(a, s.id === a.id)
|
||||
.innerJoin(i, i.id === a.itemId),
|
||||
a.itemId === itemId && i.cid === coll
|
||||
).build
|
||||
.query[(RAttachmentPreview, Int)]
|
||||
.to[Vector]
|
||||
.map(_.sortBy(_._2).headOption.map(_._1))
|
||||
@ -102,22 +149,33 @@ object RAttachmentPreview {
|
||||
): ConnectionIO[Vector[(RAttachmentPreview, FileMeta)]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
val aId = Columns.id.prefix("a")
|
||||
val afileMeta = fileId.prefix("a")
|
||||
val bPos = RAttachment.Columns.position.prefix("b")
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val mId = RFileMeta.Columns.id.prefix("m")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val afileMeta = fileId.prefix("a")
|
||||
// val bPos = RAttachment.Columns.position.prefix("b")
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val mId = RFileMeta.Columns.id.prefix("m")
|
||||
//
|
||||
// val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++ fr"INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId)
|
||||
// val where = bItem.is(id)
|
||||
//
|
||||
// (selectSimple(cols, from, where) ++ orderBy(bPos.asc))
|
||||
// .query[(RAttachmentPreview, FileMeta)]
|
||||
// .to[Vector]
|
||||
val a = RAttachmentPreview.as("a")
|
||||
val b = RAttachment.as("b")
|
||||
val m = RFileMeta.as("m")
|
||||
|
||||
val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++ fr"INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId)
|
||||
val where = bItem.is(id)
|
||||
|
||||
(selectSimple(cols, from, where) ++ orderBy(bPos.asc))
|
||||
.query[(RAttachmentPreview, FileMeta)]
|
||||
.to[Vector]
|
||||
Select(
|
||||
select(a.all, m.all),
|
||||
from(a)
|
||||
.innerJoin(m, a.fileId === m.id)
|
||||
.innerJoin(b, b.id === a.id),
|
||||
b.itemId === id
|
||||
).orderBy(b.position.asc).build.query[(RAttachmentPreview, FileMeta)].to[Vector]
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,8 +1,10 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
import bitpeace.FileMeta
|
||||
import doobie._
|
||||
@ -19,10 +21,24 @@ case class RAttachmentSource(
|
||||
)
|
||||
|
||||
object RAttachmentSource {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "attachment_source"
|
||||
|
||||
val id = Column[Ident]("id", this)
|
||||
val fileId = Column[Ident]("file_id", this)
|
||||
val name = Column[String]("filename", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
|
||||
val all = NonEmptyList.of[Column[_]](id, fileId, name, created)
|
||||
}
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
val table = fr"attachment_source"
|
||||
|
||||
object Columns {
|
||||
import docspell.store.impl._
|
||||
val id = Column("id")
|
||||
val fileId = Column("file_id")
|
||||
val name = Column("filename")
|
||||
@ -31,67 +47,90 @@ object RAttachmentSource {
|
||||
val all = List(id, fileId, name, created)
|
||||
}
|
||||
|
||||
import Columns._
|
||||
|
||||
def of(ra: RAttachment): RAttachmentSource =
|
||||
RAttachmentSource(ra.id, ra.fileId, ra.name, ra.created)
|
||||
|
||||
def insert(v: RAttachmentSource): ConnectionIO[Int] =
|
||||
insertRow(table, all, fr"${v.id},${v.fileId},${v.name},${v.created}").update.run
|
||||
DML.insert(T, T.all, fr"${v.id},${v.fileId},${v.name},${v.created}")
|
||||
|
||||
def findById(attachId: Ident): ConnectionIO[Option[RAttachmentSource]] =
|
||||
selectSimple(all, table, id.is(attachId)).query[RAttachmentSource].option
|
||||
run(select(T.all), from(T), T.id === attachId).query[RAttachmentSource].option
|
||||
|
||||
def isSameFile(attachId: Ident, file: Ident): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, and(id.is(attachId), fileId.is(file)))
|
||||
Select(count(T.id).s, from(T), T.id === attachId && T.fileId === file).build
|
||||
.query[Int]
|
||||
.unique
|
||||
.map(_ > 0)
|
||||
|
||||
def isConverted(attachId: Ident): ConnectionIO[Boolean] = {
|
||||
val sId = Columns.id.prefix("s")
|
||||
val sFile = Columns.fileId.prefix("s")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aFile = RAttachment.Columns.fileId.prefix("a")
|
||||
val s = RAttachmentSource.as("s")
|
||||
val a = RAttachment.as("a")
|
||||
Select(
|
||||
count(a.id).s,
|
||||
from(s).innerJoin(a, a.id === s.id),
|
||||
a.id === attachId && a.fileId <> s.fileId
|
||||
).build.query[Int].unique.map(_ > 0)
|
||||
|
||||
val from = table ++ fr"s INNER JOIN" ++
|
||||
RAttachment.table ++ fr"a ON" ++ aId.is(sId)
|
||||
|
||||
selectCount(aId, from, and(aId.is(attachId), aFile.isNot(sFile)))
|
||||
.query[Int]
|
||||
.unique
|
||||
.map(_ > 0)
|
||||
// val sId = Columns.id.prefix("s")
|
||||
// val sFile = Columns.fileId.prefix("s")
|
||||
// val aId = RAttachment.Columns.id.prefix("a")
|
||||
// val aFile = RAttachment.Columns.fileId.prefix("a")
|
||||
//
|
||||
// val from = table ++ fr"s INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"a ON" ++ aId.is(sId)
|
||||
//
|
||||
// selectCount(aId, from, and(aId.is(attachId), aFile.isNot(sFile)))
|
||||
// .query[Int]
|
||||
// .unique
|
||||
// .map(_ > 0)
|
||||
}
|
||||
|
||||
def delete(attachId: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, id.is(attachId)).update.run
|
||||
DML.delete(T, T.id === attachId)
|
||||
|
||||
def findByIdAndCollective(
|
||||
attachId: Ident,
|
||||
collective: Ident
|
||||
): ConnectionIO[Option[RAttachmentSource]] = {
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val aId = Columns.id.prefix("a")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val iId = RItem.Columns.id.prefix("i")
|
||||
// val iColl = RItem.Columns.cid.prefix("i")
|
||||
//
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
// fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
//
|
||||
// val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective))
|
||||
//
|
||||
// selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentSource].option
|
||||
val b = RAttachment.as("b")
|
||||
val a = RAttachmentSource.as("a")
|
||||
val i = RItem.as("i")
|
||||
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId)
|
||||
|
||||
val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective))
|
||||
|
||||
selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentSource].option
|
||||
Select(
|
||||
select(a.all),
|
||||
from(a)
|
||||
.innerJoin(b, a.id === b.id)
|
||||
.innerJoin(i, i.id === b.itemId),
|
||||
a.id === attachId && b.id === attachId && i.cid === collective
|
||||
).build.query[RAttachmentSource].option
|
||||
}
|
||||
|
||||
def findByItem(itemId: Ident): ConnectionIO[Vector[RAttachmentSource]] = {
|
||||
val sId = Columns.id.prefix("s")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
// val sId = Columns.id.prefix("s")
|
||||
// val aId = RAttachment.Columns.id.prefix("a")
|
||||
// val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
//
|
||||
// val from = table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId)
|
||||
// selectSimple(all.map(_.prefix("s")), from, aItem.is(itemId))
|
||||
// .query[RAttachmentSource]
|
||||
// .to[Vector]
|
||||
|
||||
val from = table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId)
|
||||
selectSimple(all.map(_.prefix("s")), from, aItem.is(itemId))
|
||||
val s = RAttachmentSource.as("s")
|
||||
val a = RAttachment.as("a")
|
||||
Select(select(s.all), from(s).innerJoin(a, a.id === s.id), a.itemId === itemId).build
|
||||
.query[RAttachmentSource]
|
||||
.to[Vector]
|
||||
}
|
||||
@ -101,22 +140,33 @@ object RAttachmentSource {
|
||||
): ConnectionIO[Vector[(RAttachmentSource, FileMeta)]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
val aId = Columns.id.prefix("a")
|
||||
val afileMeta = fileId.prefix("a")
|
||||
val bPos = RAttachment.Columns.position.prefix("b")
|
||||
val bId = RAttachment.Columns.id.prefix("b")
|
||||
val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
val mId = RFileMeta.Columns.id.prefix("m")
|
||||
// val aId = Columns.id.prefix("a")
|
||||
// val afileMeta = fileId.prefix("a")
|
||||
// val bPos = RAttachment.Columns.position.prefix("b")
|
||||
// val bId = RAttachment.Columns.id.prefix("b")
|
||||
// val bItem = RAttachment.Columns.itemId.prefix("b")
|
||||
// val mId = RFileMeta.Columns.id.prefix("m")
|
||||
//
|
||||
// val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
// val from = table ++ fr"a INNER JOIN" ++
|
||||
// RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++ fr"INNER JOIN" ++
|
||||
// RAttachment.table ++ fr"b ON" ++ aId.is(bId)
|
||||
// val where = bItem.is(id)
|
||||
//
|
||||
// (selectSimple(cols, from, where) ++ orderBy(bPos.asc))
|
||||
// .query[(RAttachmentSource, FileMeta)]
|
||||
// .to[Vector]
|
||||
val a = RAttachmentSource.as("a")
|
||||
val b = RAttachment.as("b")
|
||||
val m = RFileMeta.as("m")
|
||||
|
||||
val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m"))
|
||||
val from = table ++ fr"a INNER JOIN" ++
|
||||
RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++ fr"INNER JOIN" ++
|
||||
RAttachment.table ++ fr"b ON" ++ aId.is(bId)
|
||||
val where = bItem.is(id)
|
||||
|
||||
(selectSimple(cols, from, where) ++ orderBy(bPos.asc))
|
||||
.query[(RAttachmentSource, FileMeta)]
|
||||
.to[Vector]
|
||||
Select(
|
||||
select(a.all, m.all),
|
||||
from(a)
|
||||
.innerJoin(m, a.fileId === m.id)
|
||||
.innerJoin(b, b.id === a.id),
|
||||
b.itemId === id
|
||||
).orderBy(b.position.asc).build.query[(RAttachmentSource, FileMeta)].to[Vector]
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
import com.github.eikek.calev._
|
||||
import doobie._
|
||||
@ -21,71 +22,69 @@ case class RClassifierSetting(
|
||||
) {}
|
||||
|
||||
object RClassifierSetting {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "classifier_setting"
|
||||
|
||||
val table = fr"classifier_setting"
|
||||
|
||||
object Columns {
|
||||
val cid = Column("cid")
|
||||
val enabled = Column("enabled")
|
||||
val schedule = Column("schedule")
|
||||
val category = Column("category")
|
||||
val itemCount = Column("item_count")
|
||||
val fileId = Column("file_id")
|
||||
val created = Column("created")
|
||||
val all = List(cid, enabled, schedule, category, itemCount, fileId, created)
|
||||
}
|
||||
import Columns._
|
||||
|
||||
def insert(v: RClassifierSetting): ConnectionIO[Int] = {
|
||||
val sql =
|
||||
insertRow(
|
||||
table,
|
||||
all,
|
||||
fr"${v.cid},${v.enabled},${v.schedule},${v.category},${v.itemCount},${v.fileId},${v.created}"
|
||||
)
|
||||
sql.update.run
|
||||
val cid = Column[Ident]("cid", this)
|
||||
val enabled = Column[Boolean]("enabled", this)
|
||||
val schedule = Column[CalEvent]("schedule", this)
|
||||
val category = Column[String]("category", this)
|
||||
val itemCount = Column[Int]("item_count", this)
|
||||
val fileId = Column[Ident]("file_id", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
val all = NonEmptyList
|
||||
.of[Column[_]](cid, enabled, schedule, category, itemCount, fileId, created)
|
||||
}
|
||||
|
||||
def updateAll(v: RClassifierSetting): ConnectionIO[Int] = {
|
||||
val sql = updateRow(
|
||||
table,
|
||||
cid.is(v.cid),
|
||||
commas(
|
||||
enabled.setTo(v.enabled),
|
||||
schedule.setTo(v.schedule),
|
||||
category.setTo(v.category),
|
||||
itemCount.setTo(v.itemCount),
|
||||
fileId.setTo(v.fileId)
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
def insert(v: RClassifierSetting): ConnectionIO[Int] =
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${v.cid},${v.enabled},${v.schedule},${v.category},${v.itemCount},${v.fileId},${v.created}"
|
||||
)
|
||||
|
||||
def updateAll(v: RClassifierSetting): ConnectionIO[Int] =
|
||||
DML.update(
|
||||
T,
|
||||
T.cid === v.cid,
|
||||
DML.set(
|
||||
T.enabled.setTo(v.enabled),
|
||||
T.schedule.setTo(v.schedule),
|
||||
T.category.setTo(v.category),
|
||||
T.itemCount.setTo(v.itemCount),
|
||||
T.fileId.setTo(v.fileId)
|
||||
)
|
||||
)
|
||||
sql.update.run
|
||||
}
|
||||
|
||||
def updateFile(coll: Ident, fid: Ident): ConnectionIO[Int] =
|
||||
updateRow(table, cid.is(coll), fileId.setTo(fid)).update.run
|
||||
DML.update(T, T.cid === coll, DML.set(T.fileId.setTo(fid)))
|
||||
|
||||
def updateSettings(v: RClassifierSetting): ConnectionIO[Int] =
|
||||
for {
|
||||
n1 <- updateRow(
|
||||
table,
|
||||
cid.is(v.cid),
|
||||
commas(
|
||||
enabled.setTo(v.enabled),
|
||||
schedule.setTo(v.schedule),
|
||||
itemCount.setTo(v.itemCount),
|
||||
category.setTo(v.category)
|
||||
n1 <- DML.update(
|
||||
T,
|
||||
T.cid === v.cid,
|
||||
DML.set(
|
||||
T.enabled.setTo(v.enabled),
|
||||
T.schedule.setTo(v.schedule),
|
||||
T.itemCount.setTo(v.itemCount),
|
||||
T.category.setTo(v.category)
|
||||
)
|
||||
).update.run
|
||||
)
|
||||
n2 <- if (n1 <= 0) insert(v) else 0.pure[ConnectionIO]
|
||||
} yield n1 + n2
|
||||
|
||||
def findById(id: Ident): ConnectionIO[Option[RClassifierSetting]] = {
|
||||
val sql = selectSimple(all, table, cid.is(id))
|
||||
val sql = run(select(T.all), from(T), T.cid === id)
|
||||
sql.query[RClassifierSetting].option
|
||||
}
|
||||
|
||||
def delete(coll: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, cid.is(coll)).update.run
|
||||
DML.delete(T, T.cid === coll)
|
||||
|
||||
case class Classifier(
|
||||
enabled: Boolean,
|
||||
|
@ -1,10 +1,11 @@
|
||||
package docspell.store.records
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import fs2.Stream
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Column
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
@ -18,58 +19,54 @@ case class RCollective(
|
||||
)
|
||||
|
||||
object RCollective {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "collective"
|
||||
|
||||
val table = fr"collective"
|
||||
val id = Column[Ident]("cid", this)
|
||||
val state = Column[CollectiveState]("state", this)
|
||||
val language = Column[Language]("doclang", this)
|
||||
val integration = Column[Boolean]("integration_enabled", this)
|
||||
val created = Column[Timestamp]("created", this)
|
||||
|
||||
object Columns {
|
||||
|
||||
val id = Column("cid")
|
||||
val state = Column("state")
|
||||
val language = Column("doclang")
|
||||
val integration = Column("integration_enabled")
|
||||
val created = Column("created")
|
||||
|
||||
val all = List(id, state, language, integration, created)
|
||||
val all = NonEmptyList.of[Column[_]](id, state, language, integration, created)
|
||||
}
|
||||
|
||||
import Columns._
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
def insert(value: RCollective): ConnectionIO[Int] = {
|
||||
val sql = insertRow(
|
||||
table,
|
||||
Columns.all,
|
||||
def insert(value: RCollective): ConnectionIO[Int] =
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${value.id},${value.state},${value.language},${value.integrationEnabled},${value.created}"
|
||||
)
|
||||
sql.update.run
|
||||
}
|
||||
|
||||
def update(value: RCollective): ConnectionIO[Int] = {
|
||||
val sql = updateRow(
|
||||
table,
|
||||
id.is(value.id),
|
||||
commas(
|
||||
state.setTo(value.state)
|
||||
def update(value: RCollective): ConnectionIO[Int] =
|
||||
DML.update(
|
||||
T,
|
||||
T.id === value.id,
|
||||
DML.set(
|
||||
T.state.setTo(value.state)
|
||||
)
|
||||
)
|
||||
sql.update.run
|
||||
}
|
||||
|
||||
def findLanguage(cid: Ident): ConnectionIO[Option[Language]] =
|
||||
selectSimple(List(language), table, id.is(cid)).query[Option[Language]].unique
|
||||
Select(T.language.s, from(T), T.id === cid).build.query[Option[Language]].unique
|
||||
|
||||
def updateLanguage(cid: Ident, lang: Language): ConnectionIO[Int] =
|
||||
updateRow(table, id.is(cid), language.setTo(lang)).update.run
|
||||
DML.update(T, T.id === cid, DML.set(T.language.setTo(lang)))
|
||||
|
||||
def updateSettings(cid: Ident, settings: Settings): ConnectionIO[Int] =
|
||||
for {
|
||||
n1 <- updateRow(
|
||||
table,
|
||||
id.is(cid),
|
||||
commas(
|
||||
language.setTo(settings.language),
|
||||
integration.setTo(settings.integrationEnabled)
|
||||
n1 <- DML.update(
|
||||
T,
|
||||
T.id === cid,
|
||||
DML.set(
|
||||
T.language.setTo(settings.language),
|
||||
T.integration.setTo(settings.integrationEnabled)
|
||||
)
|
||||
).update.run
|
||||
)
|
||||
cls <-
|
||||
Timestamp
|
||||
.current[ConnectionIO]
|
||||
@ -83,66 +80,64 @@ object RCollective {
|
||||
} yield n1 + n2
|
||||
|
||||
def getSettings(coll: Ident): ConnectionIO[Option[Settings]] = {
|
||||
val cId = id.prefix("c")
|
||||
val CS = RClassifierSetting.Columns
|
||||
val csCid = CS.cid.prefix("cs")
|
||||
val c = RCollective.as("c")
|
||||
val cs = RClassifierSetting.as("cs")
|
||||
|
||||
val cols = Seq(
|
||||
language.prefix("c"),
|
||||
integration.prefix("c"),
|
||||
CS.enabled.prefix("cs"),
|
||||
CS.schedule.prefix("cs"),
|
||||
CS.itemCount.prefix("cs"),
|
||||
CS.category.prefix("cs")
|
||||
)
|
||||
val from = table ++ fr"c LEFT JOIN" ++
|
||||
RClassifierSetting.table ++ fr"cs ON" ++ csCid.is(cId)
|
||||
|
||||
selectSimple(cols, from, cId.is(coll))
|
||||
.query[Settings]
|
||||
.option
|
||||
Select(
|
||||
select(
|
||||
c.language.s,
|
||||
c.integration.s,
|
||||
cs.enabled.s,
|
||||
cs.schedule.s,
|
||||
cs.itemCount.s,
|
||||
cs.category.s
|
||||
),
|
||||
from(c).leftJoin(cs, cs.cid === c.id),
|
||||
c.id === coll
|
||||
).build.query[Settings].option
|
||||
}
|
||||
|
||||
def findById(cid: Ident): ConnectionIO[Option[RCollective]] = {
|
||||
val sql = selectSimple(all, table, id.is(cid))
|
||||
val sql = run(select(T.all), from(T), T.id === cid)
|
||||
sql.query[RCollective].option
|
||||
}
|
||||
|
||||
def findByItem(itemId: Ident): ConnectionIO[Option[RCollective]] = {
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val cId = id.prefix("c")
|
||||
val from = RItem.table ++ fr"i INNER JOIN" ++ table ++ fr"c ON" ++ iColl.is(cId)
|
||||
selectSimple(all.map(_.prefix("c")), from, iId.is(itemId)).query[RCollective].option
|
||||
val i = RItem.as("i")
|
||||
val c = RCollective.as("c")
|
||||
Select(
|
||||
select(c.all),
|
||||
from(i).innerJoin(c, i.cid === c.id),
|
||||
i.id === itemId
|
||||
).build.query[RCollective].option
|
||||
}
|
||||
|
||||
def existsById(cid: Ident): ConnectionIO[Boolean] = {
|
||||
val sql = selectCount(id, table, id.is(cid))
|
||||
val sql = Select(count(T.id).s, from(T), T.id === cid).build
|
||||
sql.query[Int].unique.map(_ > 0)
|
||||
}
|
||||
|
||||
def findAll(order: Columns.type => Column): ConnectionIO[Vector[RCollective]] = {
|
||||
val sql = selectSimple(all, table, Fragment.empty) ++ orderBy(order(Columns).f)
|
||||
sql.query[RCollective].to[Vector]
|
||||
def findAll(order: Table => Column[_]): ConnectionIO[Vector[RCollective]] = {
|
||||
val sql = Select(select(T.all), from(T)).orderBy(order(T))
|
||||
sql.build.query[RCollective].to[Vector]
|
||||
}
|
||||
|
||||
def streamAll(order: Columns.type => Column): Stream[ConnectionIO, RCollective] = {
|
||||
val sql = selectSimple(all, table, Fragment.empty) ++ orderBy(order(Columns).f)
|
||||
sql.query[RCollective].stream
|
||||
def streamAll(order: Table => Column[_]): Stream[ConnectionIO, RCollective] = {
|
||||
val sql = Select(select(T.all), from(T)).orderBy(order(T))
|
||||
sql.build.query[RCollective].stream
|
||||
}
|
||||
|
||||
def findByAttachment(attachId: Ident): ConnectionIO[Option[RCollective]] = {
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val cId = Columns.id.prefix("c")
|
||||
|
||||
val from = table ++ fr"c INNER JOIN" ++
|
||||
RItem.table ++ fr"i ON" ++ cId.is(iColl) ++ fr"INNER JOIN" ++
|
||||
RAttachment.table ++ fr"a ON" ++ aItem.is(iId)
|
||||
|
||||
selectSimple(all.map(_.prefix("c")), from, aId.is(attachId)).query[RCollective].option
|
||||
val i = RItem.as("i")
|
||||
val a = RAttachment.as("a")
|
||||
val c = RCollective.as("c")
|
||||
Select(
|
||||
select(c.all),
|
||||
from(c)
|
||||
.innerJoin(i, c.id === i.cid)
|
||||
.innerJoin(a, a.itemId === i.id),
|
||||
a.id === attachId
|
||||
).build.query[RCollective].option
|
||||
}
|
||||
|
||||
case class Settings(
|
||||
|
@ -1,11 +1,13 @@
|
||||
package docspell.store.records
|
||||
|
||||
import java.time.Instant
|
||||
|
||||
import cats.data.NonEmptyList
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
import docspell.store.syntax.MimeTypes._
|
||||
|
||||
import bitpeace.FileMeta
|
||||
@ -14,26 +16,30 @@ import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
object RFileMeta {
|
||||
final case class Table(alias: Option[String]) extends TableDef {
|
||||
val tableName = "filemeta"
|
||||
|
||||
val table = fr"filemeta"
|
||||
val id = Column[Ident]("id", this)
|
||||
val timestamp = Column[Instant]("timestamp", this)
|
||||
val mimetype = Column[Mimetype]("mimetype", this)
|
||||
val length = Column[Long]("length", this)
|
||||
val checksum = Column[String]("checksum", this)
|
||||
val chunks = Column[Int]("chunks", this)
|
||||
val chunksize = Column[Int]("chunksize", this)
|
||||
|
||||
object Columns {
|
||||
val id = Column("id")
|
||||
val timestamp = Column("timestamp")
|
||||
val mimetype = Column("mimetype")
|
||||
val length = Column("length")
|
||||
val checksum = Column("checksum")
|
||||
val chunks = Column("chunks")
|
||||
val chunksize = Column("chunksize")
|
||||
|
||||
val all = List(id, timestamp, mimetype, length, checksum, chunks, chunksize)
|
||||
val all = NonEmptyList
|
||||
.of[Column[_]](id, timestamp, mimetype, length, checksum, chunks, chunksize)
|
||||
|
||||
}
|
||||
|
||||
val T = Table(None)
|
||||
def as(alias: String): Table =
|
||||
Table(Some(alias))
|
||||
|
||||
def findById(fid: Ident): ConnectionIO[Option[FileMeta]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
selectSimple(Columns.all, table, Columns.id.is(fid)).query[FileMeta].option
|
||||
run(select(T.all), from(T), T.id === fid).query[FileMeta].option
|
||||
}
|
||||
|
||||
def findByIds(ids: List[Ident]): ConnectionIO[Vector[FileMeta]] = {
|
||||
@ -41,7 +47,7 @@ object RFileMeta {
|
||||
|
||||
NonEmptyList.fromList(ids) match {
|
||||
case Some(nel) =>
|
||||
selectSimple(Columns.all, table, Columns.id.isIn(nel)).query[FileMeta].to[Vector]
|
||||
run(select(T.all), from(T), T.id.in(nel)).query[FileMeta].to[Vector]
|
||||
case None =>
|
||||
Vector.empty[FileMeta].pure[ConnectionIO]
|
||||
}
|
||||
@ -50,7 +56,7 @@ object RFileMeta {
|
||||
def findMime(fid: Ident): ConnectionIO[Option[MimeType]] = {
|
||||
import bitpeace.sql._
|
||||
|
||||
selectSimple(Seq(Columns.mimetype), table, Columns.id.is(fid))
|
||||
run(select(T.mimetype), from(T), T.id === fid)
|
||||
.query[Mimetype]
|
||||
.option
|
||||
.map(_.map(_.toLocal))
|
||||
|
@ -5,9 +5,8 @@ import cats.effect.Sync
|
||||
import cats.implicits._
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.impl._
|
||||
import docspell.store.qb.{Select, TableDef}
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
@ -110,8 +109,9 @@ object RItem {
|
||||
Table(Some(alias))
|
||||
|
||||
val table = fr"item"
|
||||
|
||||
object Columns {
|
||||
import docspell.store.impl._
|
||||
|
||||
val id = Column("itemid")
|
||||
val cid = Column("cid")
|
||||
val name = Column("name")
|
||||
@ -149,19 +149,21 @@ object RItem {
|
||||
folder
|
||||
)
|
||||
}
|
||||
import Columns._
|
||||
|
||||
private val currentTime =
|
||||
Timestamp.current[ConnectionIO]
|
||||
|
||||
def insert(v: RItem): ConnectionIO[Int] =
|
||||
insertRow(
|
||||
table,
|
||||
all,
|
||||
DML.insert(
|
||||
T,
|
||||
T.all,
|
||||
fr"${v.id},${v.cid},${v.name},${v.itemDate},${v.source},${v.direction},${v.state}," ++
|
||||
fr"${v.corrOrg},${v.corrPerson},${v.concPerson},${v.concEquipment},${v.inReplyTo},${v.dueDate}," ++
|
||||
fr"${v.created},${v.updated},${v.notes},${v.folderId}"
|
||||
).update.run
|
||||
)
|
||||
|
||||
def getCollective(itemId: Ident): ConnectionIO[Option[Ident]] =
|
||||
selectSimple(List(cid), table, id.is(itemId)).query[Ident].option
|
||||
Select(T.cid.s, from(T), T.id === itemId).build.query[Ident].option
|
||||
|
||||
def updateState(
|
||||
itemId: Ident,
|
||||
@ -170,11 +172,11 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.is(itemId), state.isIn(existing)),
|
||||
commas(state.setTo(itemState), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id === itemId && T.state.in(existing),
|
||||
DML.set(T.state.setTo(itemState), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateStateForCollective(
|
||||
@ -184,11 +186,11 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(state.setTo(itemState), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.state.setTo(itemState), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateDirection(
|
||||
@ -198,11 +200,11 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(incoming.setTo(dir), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.incoming.setTo(dir), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateCorrOrg(
|
||||
@ -212,21 +214,21 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(corrOrg.setTo(org), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.corrOrg.setTo(org), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def removeCorrOrg(coll: Ident, currentOrg: Ident): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), corrOrg.is(Some(currentOrg))),
|
||||
commas(corrOrg.setTo(None: Option[Ident]), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.cid === coll && T.corrOrg === currentOrg,
|
||||
DML.set(T.corrOrg.setTo(None: Option[Ident]), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateCorrPerson(
|
||||
@ -236,21 +238,21 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(corrPerson.setTo(person), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.corrPerson.setTo(person), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def removeCorrPerson(coll: Ident, currentPerson: Ident): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), corrPerson.is(Some(currentPerson))),
|
||||
commas(corrPerson.setTo(None: Option[Ident]), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.cid === coll && T.corrPerson === currentPerson,
|
||||
DML.set(T.corrPerson.setTo(None: Option[Ident]), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateConcPerson(
|
||||
@ -260,21 +262,21 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(concPerson.setTo(person), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.concPerson.setTo(person), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def removeConcPerson(coll: Ident, currentPerson: Ident): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), concPerson.is(Some(currentPerson))),
|
||||
commas(concPerson.setTo(None: Option[Ident]), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.cid === coll && T.concPerson === currentPerson,
|
||||
DML.set(T.concPerson.setTo(None: Option[Ident]), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateConcEquip(
|
||||
@ -284,21 +286,21 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(concEquipment.setTo(equip), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.concEquipment.setTo(equip), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def removeConcEquip(coll: Ident, currentEquip: Ident): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), concEquipment.is(Some(currentEquip))),
|
||||
commas(concEquipment.setTo(None: Option[Ident]), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.cid === coll && T.concEquipment === currentEquip,
|
||||
DML.set(T.concEquipment.setTo(None: Option[Ident]), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateFolder(
|
||||
@ -308,31 +310,31 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(cid.is(coll), id.is(itemId)),
|
||||
commas(folder.setTo(folderId), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.cid === coll && T.id === itemId,
|
||||
DML.set(T.folder.setTo(folderId), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateNotes(itemId: Ident, coll: Ident, text: Option[String]): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.is(itemId), cid.is(coll)),
|
||||
commas(notes.setTo(text), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id === itemId && T.cid === coll,
|
||||
DML.set(T.notes.setTo(text), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateName(itemId: Ident, coll: Ident, itemName: String): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.is(itemId), cid.is(coll)),
|
||||
commas(name.setTo(itemName), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id === itemId && T.cid === coll,
|
||||
DML.set(T.name.setTo(itemName), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateDate(
|
||||
@ -342,11 +344,11 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(itemDate.setTo(date), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.itemDate.setTo(date), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def updateDueDate(
|
||||
@ -356,50 +358,50 @@ object RItem {
|
||||
): ConnectionIO[Int] =
|
||||
for {
|
||||
t <- currentTime
|
||||
n <- updateRow(
|
||||
table,
|
||||
and(id.isIn(itemIds), cid.is(coll)),
|
||||
commas(dueDate.setTo(date), updated.setTo(t))
|
||||
).update.run
|
||||
n <- DML.update(
|
||||
T,
|
||||
T.id.in(itemIds) && T.cid === coll,
|
||||
DML.set(T.dueDate.setTo(date), T.updated.setTo(t))
|
||||
)
|
||||
} yield n
|
||||
|
||||
def deleteByIdAndCollective(itemId: Ident, coll: Ident): ConnectionIO[Int] =
|
||||
deleteFrom(table, and(id.is(itemId), cid.is(coll))).update.run
|
||||
DML.delete(T, T.id === itemId && T.cid === coll)
|
||||
|
||||
def existsById(itemId: Ident): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, id.is(itemId)).query[Int].unique.map(_ > 0)
|
||||
Select(count(T.id).s, from(T), T.id === itemId).build.query[Int].unique.map(_ > 0)
|
||||
|
||||
def existsByIdAndCollective(itemId: Ident, coll: Ident): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, and(id.is(itemId), cid.is(coll))).query[Int].unique.map(_ > 0)
|
||||
Select(count(T.id).s, from(T), T.id === itemId && T.cid === coll).build
|
||||
.query[Int]
|
||||
.unique
|
||||
.map(_ > 0)
|
||||
|
||||
def existsByIdsAndCollective(
|
||||
itemIds: NonEmptyList[Ident],
|
||||
coll: Ident
|
||||
): ConnectionIO[Boolean] =
|
||||
selectCount(id, table, and(id.isIn(itemIds), cid.is(coll)))
|
||||
Select(count(T.id).s, from(T), T.id.in(itemIds) && T.cid === coll).build
|
||||
.query[Int]
|
||||
.unique
|
||||
.map(_ == itemIds.size)
|
||||
|
||||
def findByIdAndCollective(itemId: Ident, coll: Ident): ConnectionIO[Option[RItem]] =
|
||||
selectSimple(all, table, and(id.is(itemId), cid.is(coll))).query[RItem].option
|
||||
run(select(T.all), from(T), T.id === itemId && T.cid === coll).query[RItem].option
|
||||
|
||||
def findById(itemId: Ident): ConnectionIO[Option[RItem]] =
|
||||
selectSimple(all, table, id.is(itemId)).query[RItem].option
|
||||
run(select(T.all), from(T), T.id === itemId).query[RItem].option
|
||||
|
||||
def checkByIdAndCollective(itemId: Ident, coll: Ident): ConnectionIO[Option[Ident]] =
|
||||
selectSimple(Seq(id), table, and(id.is(itemId), cid.is(coll))).query[Ident].option
|
||||
Select(T.id.s, from(T), T.id === itemId && T.cid === coll).build.query[Ident].option
|
||||
|
||||
def removeFolder(folderId: Ident): ConnectionIO[Int] = {
|
||||
val empty: Option[Ident] = None
|
||||
updateRow(table, folder.is(folderId), folder.setTo(empty)).update.run
|
||||
DML.update(T, T.folder === folderId, DML.set(T.folder.setTo(empty)))
|
||||
}
|
||||
|
||||
def filterItemsFragment(items: NonEmptyList[Ident], coll: Ident): Select = {
|
||||
import docspell.store.qb.DSL._
|
||||
|
||||
def filterItemsFragment(items: NonEmptyList[Ident], coll: Ident): Select =
|
||||
Select(select(T.id), from(T), T.cid === coll && T.id.in(items))
|
||||
}
|
||||
|
||||
def filterItems(items: NonEmptyList[Ident], coll: Ident): ConnectionIO[Vector[Ident]] =
|
||||
filterItemsFragment(items, coll).build.query[Ident].to[Vector]
|
||||
|
Loading…
Reference in New Issue
Block a user