mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-04-05 10:59:33 +00:00
Convert all query libs besides QItem
This commit is contained in:
parent
fd6d09587d
commit
a355767fdb
@ -59,8 +59,8 @@ object OItemSearch {
|
||||
type Query = QItem.Query
|
||||
val Query = QItem.Query
|
||||
|
||||
type Batch = QItem.Batch
|
||||
val Batch = QItem.Batch
|
||||
type Batch = docspell.store.queries.Batch
|
||||
val Batch = docspell.store.queries.Batch
|
||||
|
||||
type ListItem = QItem.ListItem
|
||||
val ListItem = QItem.ListItem
|
||||
|
@ -64,6 +64,11 @@ object Select {
|
||||
|
||||
def distinct: SimpleSelect =
|
||||
copy(distinctFlag = true)
|
||||
|
||||
def where(c: Option[Condition]): SimpleSelect =
|
||||
copy(where = c)
|
||||
def where(c: Condition): SimpleSelect =
|
||||
copy(where = Some(c))
|
||||
}
|
||||
|
||||
case class Union(q: Select, qs: Vector[Select]) extends Select
|
||||
|
@ -0,0 +1,22 @@
|
||||
package docspell.store.queries
|
||||
|
||||
case class Batch(offset: Int, limit: Int) {
|
||||
def restrictLimitTo(n: Int): Batch =
|
||||
Batch(offset, math.min(n, limit))
|
||||
|
||||
def next: Batch =
|
||||
Batch(offset + limit, limit)
|
||||
|
||||
def first: Batch =
|
||||
Batch(0, limit)
|
||||
}
|
||||
|
||||
object Batch {
|
||||
val all: Batch = Batch(0, Int.MaxValue)
|
||||
|
||||
def page(n: Int, size: Int): Batch =
|
||||
Batch(n * size, size)
|
||||
|
||||
def limit(c: Int): Batch =
|
||||
Batch(0, c)
|
||||
}
|
@ -8,15 +8,20 @@ import fs2.Stream
|
||||
import docspell.common._
|
||||
import docspell.common.syntax.all._
|
||||
import docspell.store.Store
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
import docspell.store.records._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
object QAttachment {
|
||||
private[this] val logger = org.log4s.getLogger
|
||||
|
||||
private val a = RAttachment.as("a")
|
||||
private val item = RItem.as("i")
|
||||
private val am = RAttachmentMeta.as("am")
|
||||
private val c = RCollective.as("c")
|
||||
|
||||
def deletePreview[F[_]: Sync](store: Store[F])(attachId: Ident): F[Int] = {
|
||||
val findPreview =
|
||||
for {
|
||||
@ -113,20 +118,13 @@ object QAttachment {
|
||||
} yield ns.sum
|
||||
|
||||
def getMetaProposals(itemId: Ident, coll: Ident): ConnectionIO[MetaProposalList] = {
|
||||
val AC = RAttachment.Columns
|
||||
val MC = RAttachmentMeta.Columns
|
||||
val IC = RItem.Columns
|
||||
|
||||
val q = fr"SELECT" ++ MC.proposals
|
||||
.prefix("m")
|
||||
.f ++ fr"FROM" ++ RAttachmentMeta.table ++ fr"m" ++
|
||||
fr"INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ AC.id
|
||||
.prefix("a")
|
||||
.is(MC.id.prefix("m")) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ AC.itemId
|
||||
.prefix("a")
|
||||
.is(IC.id.prefix("i")) ++
|
||||
fr"WHERE" ++ and(AC.itemId.prefix("a").is(itemId), IC.cid.prefix("i").is(coll))
|
||||
val q = Select(
|
||||
am.proposals.s,
|
||||
from(am)
|
||||
.innerJoin(a, a.id === am.id)
|
||||
.innerJoin(item, a.itemId === item.id),
|
||||
a.itemId === itemId && item.cid === coll
|
||||
).build
|
||||
|
||||
for {
|
||||
ml <- q.query[MetaProposalList].to[Vector]
|
||||
@ -137,24 +135,13 @@ object QAttachment {
|
||||
attachId: Ident,
|
||||
collective: Ident
|
||||
): ConnectionIO[Option[RAttachmentMeta]] = {
|
||||
val AC = RAttachment.Columns
|
||||
val MC = RAttachmentMeta.Columns
|
||||
val IC = RItem.Columns
|
||||
|
||||
val q =
|
||||
fr"SELECT" ++ commas(
|
||||
MC.all.map(_.prefix("m").f)
|
||||
) ++ fr"FROM" ++ RItem.table ++ fr"i" ++
|
||||
fr"INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ IC.id
|
||||
.prefix("i")
|
||||
.is(AC.itemId.prefix("a")) ++
|
||||
fr"INNER JOIN" ++ RAttachmentMeta.table ++ fr"m ON" ++ AC.id
|
||||
.prefix("a")
|
||||
.is(MC.id.prefix("m")) ++
|
||||
fr"WHERE" ++ and(
|
||||
AC.id.prefix("a").is(attachId),
|
||||
IC.cid.prefix("i").is(collective)
|
||||
)
|
||||
val q = Select(
|
||||
select(am.all),
|
||||
from(item)
|
||||
.innerJoin(a, a.itemId === item.id)
|
||||
.innerJoin(am, am.id === a.id),
|
||||
a.id === attachId && item.cid === collective
|
||||
).build
|
||||
|
||||
q.query[RAttachmentMeta].option
|
||||
}
|
||||
@ -171,31 +158,16 @@ object QAttachment {
|
||||
def allAttachmentMetaAndName(
|
||||
coll: Option[Ident],
|
||||
chunkSize: Int
|
||||
): Stream[ConnectionIO, ContentAndName] = {
|
||||
val aId = RAttachment.Columns.id.prefix("a")
|
||||
val aItem = RAttachment.Columns.itemId.prefix("a")
|
||||
val aName = RAttachment.Columns.name.prefix("a")
|
||||
val mId = RAttachmentMeta.Columns.id.prefix("m")
|
||||
val mContent = RAttachmentMeta.Columns.content.prefix("m")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val iFolder = RItem.Columns.folder.prefix("i")
|
||||
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" ++ Fragment.const(RCollective.T.tableName) ++ fr"c ON" ++ cId.is(
|
||||
iColl
|
||||
)
|
||||
|
||||
val where = coll.map(cid => iColl.is(cid)).getOrElse(Fragment.empty)
|
||||
|
||||
selectSimple(cols, from, where)
|
||||
): Stream[ConnectionIO, ContentAndName] =
|
||||
Select(
|
||||
select(a.id, a.itemId, item.cid, item.folder, c.language, a.name, am.content),
|
||||
from(a)
|
||||
.innerJoin(am, am.id === a.id)
|
||||
.innerJoin(item, item.id === a.itemId)
|
||||
.innerJoin(c, c.id === item.cid)
|
||||
).where(coll.map(cid => item.cid === cid))
|
||||
.build
|
||||
.query[ContentAndName]
|
||||
.streamWithChunkSize(chunkSize)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,14 +5,20 @@ import fs2.Stream
|
||||
|
||||
import docspell.common.ContactKind
|
||||
import docspell.common.{Direction, Ident}
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.qb.{GroupBy, Select}
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
import docspell.store.records._
|
||||
|
||||
import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
object QCollective {
|
||||
private val ti = RTagItem.as("ti")
|
||||
private val t = RTag.as("t")
|
||||
private val ro = ROrganization.as("o")
|
||||
private val rp = RPerson.as("p")
|
||||
private val rc = RContact.as("c")
|
||||
private val i = RItem.as("i")
|
||||
|
||||
case class Names(org: Vector[String], pers: Vector[String], equip: Vector[String])
|
||||
object Names {
|
||||
@ -37,17 +43,16 @@ object QCollective {
|
||||
)
|
||||
|
||||
def getInsights(coll: Ident): ConnectionIO[InsightData] = {
|
||||
val IC = RItem.Columns
|
||||
val q0 = selectCount(
|
||||
IC.id,
|
||||
RItem.table,
|
||||
and(IC.cid.is(coll), IC.incoming.is(Direction.incoming))
|
||||
).query[Int].unique
|
||||
val q1 = selectCount(
|
||||
IC.id,
|
||||
RItem.table,
|
||||
and(IC.cid.is(coll), IC.incoming.is(Direction.outgoing))
|
||||
).query[Int].unique
|
||||
val q0 = Select(
|
||||
count(i.id).s,
|
||||
from(i),
|
||||
i.cid === coll && i.incoming === Direction.incoming
|
||||
).build.query[Int].unique
|
||||
val q1 = Select(
|
||||
count(i.id).s,
|
||||
from(i),
|
||||
i.cid === coll && i.incoming === Direction.outgoing
|
||||
).build.query[Int].unique
|
||||
|
||||
val fileSize = sql"""
|
||||
select sum(length) from (
|
||||
@ -78,10 +83,6 @@ object QCollective {
|
||||
}
|
||||
|
||||
def tagCloud(coll: Ident): ConnectionIO[List[TagCount]] = {
|
||||
import docspell.store.qb.DSL._
|
||||
|
||||
val ti = RTagItem.as("ti")
|
||||
val t = RTag.as("t")
|
||||
val sql =
|
||||
Select(
|
||||
select(t.all).append(count(ti.itemId).s),
|
||||
@ -97,13 +98,6 @@ object QCollective {
|
||||
query: Option[String],
|
||||
kind: Option[ContactKind]
|
||||
): Stream[ConnectionIO, RContact] = {
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
|
||||
val ro = ROrganization.as("o")
|
||||
val rp = RPerson.as("p")
|
||||
val rc = RContact.as("c")
|
||||
|
||||
val orgCond = Select(select(ro.oid), from(ro), ro.cid === coll)
|
||||
val persCond = Select(select(rp.pid), from(rp), rp.cid === coll)
|
||||
val valueFilter = query.map(s => rc.value.like(s"%${s.toLowerCase}%"))
|
||||
|
@ -29,45 +29,14 @@ object QCustomField {
|
||||
nameQuery: Option[String],
|
||||
fieldId: Option[Ident]
|
||||
): Select = {
|
||||
// val fId = RCustomField.Columns.id.prefix("f")
|
||||
// val fColl = RCustomField.Columns.cid.prefix("f")
|
||||
// val fName = RCustomField.Columns.name.prefix("f")
|
||||
// val fLabel = RCustomField.Columns.label.prefix("f")
|
||||
// val vField = RCustomFieldValue.Columns.field.prefix("v")
|
||||
//
|
||||
// val join = RCustomField.table ++ fr"f LEFT OUTER JOIN" ++
|
||||
// RCustomFieldValue.table ++ fr"v ON" ++ fId.is(vField)
|
||||
//
|
||||
// val cols = RCustomField.Columns.all.map(_.prefix("f")) :+ Column("COUNT(v.id)")
|
||||
//
|
||||
// val nameCond = nameQuery.map(QueryWildcard.apply) match {
|
||||
// case Some(q) =>
|
||||
// or(fName.lowerLike(q), and(fLabel.isNotNull, fLabel.lowerLike(q)))
|
||||
// case None =>
|
||||
// Fragment.empty
|
||||
// }
|
||||
// val fieldCond = fieldId match {
|
||||
// case Some(id) =>
|
||||
// fId.is(id)
|
||||
// case None =>
|
||||
// Fragment.empty
|
||||
// }
|
||||
// val cond = and(fColl.is(coll), nameCond, fieldCond)
|
||||
//
|
||||
// val group = NonEmptyList.fromList(RCustomField.Columns.all) match {
|
||||
// case Some(nel) => groupBy(nel.map(_.prefix("f")))
|
||||
// case None => Fragment.empty
|
||||
// }
|
||||
//
|
||||
// selectSimple(cols, join, cond) ++ group
|
||||
|
||||
val nameFilter = nameQuery.map { q =>
|
||||
f.name.likes(q) || (f.label.isNotNull && f.label.like(q))
|
||||
}
|
||||
|
||||
Select(
|
||||
f.all.map(_.s).append(count(v.id).as("num")),
|
||||
from(f).leftJoin(v, f.id === v.field),
|
||||
from(f)
|
||||
.leftJoin(v, f.id === v.field),
|
||||
f.cid === coll &&? nameFilter &&? fieldId.map(fid => f.id === fid),
|
||||
GroupBy(f.all)
|
||||
)
|
||||
|
@ -259,27 +259,6 @@ object QItem {
|
||||
)
|
||||
}
|
||||
|
||||
case class Batch(offset: Int, limit: Int) {
|
||||
def restrictLimitTo(n: Int): Batch =
|
||||
Batch(offset, math.min(n, limit))
|
||||
|
||||
def next: Batch =
|
||||
Batch(offset + limit, limit)
|
||||
|
||||
def first: Batch =
|
||||
Batch(0, limit)
|
||||
}
|
||||
|
||||
object Batch {
|
||||
val all: Batch = Batch(0, Int.MaxValue)
|
||||
|
||||
def page(n: Int, size: Int): Batch =
|
||||
Batch(n * size, size)
|
||||
|
||||
def limit(c: Int): Batch =
|
||||
Batch(0, c)
|
||||
}
|
||||
|
||||
private def findCustomFieldValuesForColl(
|
||||
coll: Ident,
|
||||
values: Seq[CustomValue]
|
||||
|
@ -3,8 +3,8 @@ package docspell.store.queries
|
||||
import cats.data.OptionT
|
||||
|
||||
import docspell.common._
|
||||
import docspell.store.impl.Column
|
||||
import docspell.store.impl.Implicits._
|
||||
import docspell.store.qb.DSL._
|
||||
import docspell.store.qb._
|
||||
import docspell.store.records._
|
||||
|
||||
import doobie._
|
||||
@ -12,6 +12,11 @@ import doobie.implicits._
|
||||
|
||||
object QMails {
|
||||
|
||||
private val item = RItem.as("i")
|
||||
private val smail = RSentMail.as("sm")
|
||||
private val mailitem = RSentMailItem.as("mi")
|
||||
private val user = RUser.as("u")
|
||||
|
||||
def delete(coll: Ident, mailId: Ident): ConnectionIO[Int] =
|
||||
(for {
|
||||
m <- OptionT(findMail(coll, mailId))
|
||||
@ -19,53 +24,28 @@ object QMails {
|
||||
n <- OptionT.liftF(RSentMail.delete(m._1.id))
|
||||
} yield k + n).getOrElse(0)
|
||||
|
||||
def findMail(coll: Ident, mailId: Ident): ConnectionIO[Option[(RSentMail, Ident)]] = {
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val smail = RSentMail.as("m")
|
||||
val mId = smail.id.column
|
||||
def findMail(coll: Ident, mailId: Ident): ConnectionIO[Option[(RSentMail, Ident)]] =
|
||||
partialFind
|
||||
.where(smail.id === mailId && item.cid === coll)
|
||||
.build
|
||||
.query[(RSentMail, Ident)]
|
||||
.option
|
||||
|
||||
val (cols, from) = partialFind
|
||||
|
||||
val cond = Seq(mId.is(mailId), iColl.is(coll))
|
||||
|
||||
selectSimple(cols, from, and(cond)).query[(RSentMail, Ident)].option
|
||||
}
|
||||
|
||||
def findMails(coll: Ident, itemId: Ident): ConnectionIO[Vector[(RSentMail, Ident)]] = {
|
||||
val smailitem = RSentMailItem.as("t")
|
||||
val smail = RSentMail.as("m")
|
||||
val iColl = RItem.Columns.cid.prefix("i")
|
||||
val tItem = smailitem.itemId.column
|
||||
val mCreated = smail.created.column
|
||||
|
||||
val (cols, from) = partialFind
|
||||
|
||||
val cond = Seq(tItem.is(itemId), iColl.is(coll))
|
||||
|
||||
(selectSimple(cols, from, and(cond)) ++ orderBy(mCreated.f) ++ fr"DESC")
|
||||
def findMails(coll: Ident, itemId: Ident): ConnectionIO[Vector[(RSentMail, Ident)]] =
|
||||
partialFind
|
||||
.where(mailitem.itemId === itemId && item.cid === coll)
|
||||
.orderBy(smail.created.desc)
|
||||
.build
|
||||
.query[(RSentMail, Ident)]
|
||||
.to[Vector]
|
||||
}
|
||||
|
||||
private def partialFind: (Seq[Column], Fragment) = {
|
||||
val user = RUser.as("u")
|
||||
val smailitem = RSentMailItem.as("t")
|
||||
val smail = RSentMail.as("m")
|
||||
val iId = RItem.Columns.id.prefix("i")
|
||||
val tItem = smailitem.itemId.column
|
||||
val tMail = smailitem.sentMailId.column
|
||||
val mId = smail.id.column
|
||||
val mUser = smail.uid.column
|
||||
|
||||
val cols = smail.all.map(_.column) :+ user.login.column
|
||||
val from = Fragment.const(smail.tableName) ++ fr"m INNER JOIN" ++
|
||||
Fragment.const(smailitem.tableName) ++ fr"t ON" ++ tMail.is(mId) ++
|
||||
fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ tItem.is(iId) ++
|
||||
fr"INNER JOIN" ++ Fragment.const(user.tableName) ++ fr"u ON" ++ user.uid.column.is(
|
||||
mUser
|
||||
private def partialFind: Select.SimpleSelect =
|
||||
Select(
|
||||
select(smail.all).append(user.login.s),
|
||||
from(smail)
|
||||
.innerJoin(mailitem, mailitem.sentMailId === smail.id)
|
||||
.innerJoin(item, mailitem.itemId === item.id)
|
||||
.innerJoin(user, user.uid === smail.uid)
|
||||
)
|
||||
|
||||
(cols.toList, from)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,15 +13,15 @@ import doobie._
|
||||
import doobie.implicits._
|
||||
|
||||
object QOrganization {
|
||||
private val p = RPerson.as("p")
|
||||
private val c = RContact.as("c")
|
||||
private val org = ROrganization.as("o")
|
||||
|
||||
def findOrgAndContact(
|
||||
coll: Ident,
|
||||
query: Option[String],
|
||||
order: ROrganization.Table => Column[_]
|
||||
): Stream[ConnectionIO, (ROrganization, Vector[RContact])] = {
|
||||
val org = ROrganization.as("o")
|
||||
val c = RContact.as("c")
|
||||
|
||||
val valFilter = query.map { q =>
|
||||
val v = s"%$q%"
|
||||
c.value.like(v) || org.name.like(v) || org.notes.like(v)
|
||||
@ -46,9 +46,6 @@ object QOrganization {
|
||||
coll: Ident,
|
||||
orgId: Ident
|
||||
): ConnectionIO[Option[(ROrganization, Vector[RContact])]] = {
|
||||
val org = ROrganization.as("o")
|
||||
val c = RContact.as("c")
|
||||
|
||||
val sql = run(
|
||||
select(org.all, c.all),
|
||||
from(org).leftJoin(c, c.orgId === org.oid),
|
||||
@ -72,19 +69,16 @@ object QOrganization {
|
||||
query: Option[String],
|
||||
order: RPerson.Table => Column[_]
|
||||
): Stream[ConnectionIO, (RPerson, Option[ROrganization], Vector[RContact])] = {
|
||||
val pers = RPerson.as("p")
|
||||
val org = ROrganization.as("o")
|
||||
val c = RContact.as("c")
|
||||
val valFilter = query
|
||||
.map(s => s"%$s%")
|
||||
.map(v => c.value.like(v) || pers.name.like(v) || pers.notes.like(v))
|
||||
.map(v => c.value.like(v) || p.name.like(v) || p.notes.like(v))
|
||||
val sql = Select(
|
||||
select(pers.all, org.all, c.all),
|
||||
from(pers)
|
||||
.leftJoin(org, org.oid === pers.oid)
|
||||
.leftJoin(c, c.personId === pers.pid),
|
||||
pers.cid === coll &&? valFilter
|
||||
).orderBy(order(pers))
|
||||
select(p.all, org.all, c.all),
|
||||
from(p)
|
||||
.leftJoin(org, org.oid === p.oid)
|
||||
.leftJoin(c, c.personId === p.pid),
|
||||
p.cid === coll &&? valFilter
|
||||
).orderBy(order(p))
|
||||
|
||||
sql.build
|
||||
.query[(RPerson, Option[ROrganization], Option[RContact])]
|
||||
@ -101,16 +95,13 @@ object QOrganization {
|
||||
coll: Ident,
|
||||
persId: Ident
|
||||
): ConnectionIO[Option[(RPerson, Option[ROrganization], Vector[RContact])]] = {
|
||||
val pers = RPerson.as("p")
|
||||
val org = ROrganization.as("o")
|
||||
val c = RContact.as("c")
|
||||
val sql =
|
||||
run(
|
||||
select(pers.all, org.all, c.all),
|
||||
from(pers)
|
||||
.leftJoin(org, pers.oid === org.oid)
|
||||
.leftJoin(c, c.personId === pers.pid),
|
||||
pers.cid === coll && pers.pid === persId
|
||||
select(p.all, org.all, c.all),
|
||||
from(p)
|
||||
.leftJoin(org, p.oid === org.oid)
|
||||
.leftJoin(c, c.personId === p.pid),
|
||||
p.cid === coll && p.pid === persId
|
||||
)
|
||||
|
||||
sql
|
||||
@ -131,9 +122,7 @@ object QOrganization {
|
||||
value: String,
|
||||
ck: Option[ContactKind],
|
||||
concerning: Option[Boolean]
|
||||
): Stream[ConnectionIO, RPerson] = {
|
||||
val p = RPerson.as("p")
|
||||
val c = RContact.as("c")
|
||||
): Stream[ConnectionIO, RPerson] =
|
||||
runDistinct(
|
||||
select(p.all),
|
||||
from(p).innerJoin(c, c.personId === p.pid),
|
||||
@ -141,7 +130,6 @@ object QOrganization {
|
||||
concerning.map(c => p.concerning === c) &&?
|
||||
ck.map(k => c.kind === k)
|
||||
).query[RPerson].stream
|
||||
}
|
||||
|
||||
def addOrg[F[_]](
|
||||
org: ROrganization,
|
||||
|
Loading…
x
Reference in New Issue
Block a user