Merge pull request #1037 from eikek/small-list-improvements

Allow to specify ordering when retrieving meta data
This commit is contained in:
mergify[bot]
2021-08-27 21:18:47 +00:00
committed by GitHub
52 changed files with 1236 additions and 208 deletions

View File

@ -12,6 +12,7 @@ case class Column[A](name: String, table: TableDef) {
def cast[B]: Column[B] =
this.asInstanceOf[Column[B]]
}
object Column {}

View File

@ -303,6 +303,12 @@ trait DSL extends DoobieMeta {
def as(otherCol: Column[_]): SelectExpr =
SelectExpr.SelectFun(dbf, Some(otherCol.name))
def asc: OrderBy =
OrderBy(SelectExpr.SelectFun(dbf, None), OrderBy.OrderType.Asc)
def desc: OrderBy =
OrderBy(SelectExpr.SelectFun(dbf, None), OrderBy.OrderType.Desc)
def ===[A](value: A)(implicit P: Put[A]): Condition =
Condition.CompareFVal(dbf.s, Operator.Eq, value)

View File

@ -135,6 +135,9 @@ object Select {
def orderBy(ob: OrderBy, obs: OrderBy*): Ordered =
Ordered(this, ob, obs.toVector)
def orderBy(ob: Nel[OrderBy]): Ordered =
Ordered(this, ob.head, ob.tail.toVector)
}
case class RawSelect(fragment: Fragment) extends Select {

View File

@ -24,9 +24,10 @@ object QCustomField {
def findAllLike(
coll: Ident,
nameQuery: Option[String]
nameQuery: Option[String],
order: RCustomField.Table => Nel[OrderBy]
): ConnectionIO[Vector[CustomFieldData]] =
findFragment(coll, nameQuery, None).build.query[CustomFieldData].to[Vector]
findFragment(coll, nameQuery, None, order).build.query[CustomFieldData].to[Vector]
def findById(field: Ident, collective: Ident): ConnectionIO[Option[CustomFieldData]] =
findFragment(collective, None, field.some).build.query[CustomFieldData].option
@ -34,7 +35,8 @@ object QCustomField {
private def findFragment(
coll: Ident,
nameQuery: Option[String],
fieldId: Option[Ident]
fieldId: Option[Ident],
order: RCustomField.Table => Nel[OrderBy] = t => Nel.of(t.name.asc)
): Select = {
val nameFilter = nameQuery.map { q =>
f.name.likes(q) || (f.label.isNotNull && f.label.like(q))
@ -46,7 +48,7 @@ object QCustomField {
.leftJoin(v, f.id === v.field),
f.cid === coll &&? nameFilter &&? fieldId.map(fid => f.id === fid),
GroupBy(f.all)
)
).orderBy(order(f))
}
final case class FieldValue(

View File

@ -7,6 +7,7 @@
package docspell.store.queries
import cats.data.OptionT
import cats.data.{NonEmptyList => Nel}
import cats.implicits._
import docspell.common._
@ -156,8 +157,11 @@ object QFolder {
).query[IdRef].to[Vector]
(for {
folder <- OptionT(findAll(account, Some(id), None, None).map(_.headOption))
memb <- OptionT.liftF(memberQ)
folder <- OptionT(
findAll(account, Some(id), None, None, (ft, _) => Nel.of(ft.name.asc))
.map(_.headOption)
)
memb <- OptionT.liftF(memberQ)
} yield folder.withMembers(memb.toList)).value
}
@ -165,7 +169,8 @@ object QFolder {
account: AccountId,
idQ: Option[Ident],
ownerLogin: Option[Ident],
nameQ: Option[String]
nameQ: Option[String],
order: (RFolder.Table, RUser.Table) => Nel[OrderBy]
): ConnectionIO[Vector[FolderItem]] = {
// with memberlogin as
// (select m.folder_id,u.login
@ -239,7 +244,7 @@ object QFolder {
nameQ.map(q => folder.name.like(s"%${q.toLowerCase}%")) &&?
ownerLogin.map(login => user.login === login)
)
).orderBy(folder.name.asc)
).orderBy(order(folder, user))
).build.query[FolderItem].to[Vector]
}

View File

@ -6,7 +6,7 @@
package docspell.store.queries
import cats.data.NonEmptyList
import cats.data.{NonEmptyList => Nel}
import cats.implicits._
import fs2._
@ -27,7 +27,7 @@ object QOrganization {
def findOrgAndContact(
coll: Ident,
query: Option[String],
order: ROrganization.Table => Column[_]
order: ROrganization.Table => Nel[OrderBy]
): Stream[ConnectionIO, (ROrganization, Vector[RContact])] = {
val valFilter = query.map { q =>
val v = s"%$q%"
@ -74,18 +74,18 @@ object QOrganization {
def findPersonAndContact(
coll: Ident,
query: Option[String],
order: RPerson.Table => Column[_]
order: (RPerson.Table, ROrganization.Table) => Nel[OrderBy]
): Stream[ConnectionIO, (RPerson, Option[ROrganization], Vector[RContact])] = {
val valFilter = query
.map(s => s"%$s%")
.map(v => c.value.like(v) || p.name.like(v) || p.notes.like(v))
.map(v => c.value.like(v) || p.name.like(v) || org.name.like(v) || p.notes.like(v))
val sql = Select(
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))
).orderBy(order(p, org))
sql.build
.query[(RPerson, Option[ROrganization], Option[RContact])]
@ -128,7 +128,7 @@ object QOrganization {
coll: Ident,
value: String,
ck: Option[ContactKind],
use: Option[NonEmptyList[PersonUse]]
use: Option[Nel[PersonUse]]
): Stream[ConnectionIO, RPerson] =
runDistinct(
select(p.all),

View File

@ -87,7 +87,7 @@ object REquipment {
def findAll(
coll: Ident,
nameQ: Option[String],
order: Table => Column[_]
order: Table => NonEmptyList[OrderBy]
): ConnectionIO[Vector[REquipment]] = {
val t = Table(None)

View File

@ -7,7 +7,7 @@
package docspell.store.records
import cats.Eq
import cats.data.NonEmptyList
import cats.data.{NonEmptyList => Nel}
import fs2.Stream
import docspell.common.{IdRef, _}
@ -52,7 +52,7 @@ object ROrganization {
val shortName = Column[String]("short_name", this)
val use = Column[OrgUse]("org_use", this)
val all =
NonEmptyList.of[Column[_]](
Nel.of[Column[_]](
oid,
cid,
name,
@ -122,7 +122,7 @@ object ROrganization {
def findLike(
coll: Ident,
orgName: String,
use: NonEmptyList[OrgUse]
use: Nel[OrgUse]
): ConnectionIO[Vector[IdRef]] =
run(
select(T.oid, T.name),
@ -163,7 +163,7 @@ object ROrganization {
def findAllRef(
coll: Ident,
nameQ: Option[String],
order: Table => Column[_]
order: Table => Nel[OrderBy]
): ConnectionIO[Vector[IdRef]] = {
val nameFilter = nameQ.map(s =>
T.name.like(s"%${s.toLowerCase}%") || T.shortName.like(s"%${s.toLowerCase}%")

View File

@ -7,7 +7,7 @@
package docspell.store.records
import cats.Eq
import cats.data.NonEmptyList
import cats.data.{NonEmptyList => Nel}
import cats.effect._
import fs2.Stream
@ -52,7 +52,7 @@ object RPerson {
val updated = Column[Timestamp]("updated", this)
val oid = Column[Ident]("oid", this)
val use = Column[PersonUse]("person_use", this)
val all = NonEmptyList.of[Column[_]](
val all = Nel.of[Column[_]](
pid,
cid,
name,
@ -122,7 +122,7 @@ object RPerson {
def findLike(
coll: Ident,
personName: String,
use: NonEmptyList[PersonUse]
use: Nel[PersonUse]
): ConnectionIO[Vector[IdRef]] =
run(
select(T.pid, T.name),
@ -134,7 +134,7 @@ object RPerson {
coll: Ident,
contactKind: ContactKind,
value: String,
use: NonEmptyList[PersonUse]
use: Nel[PersonUse]
): ConnectionIO[Vector[IdRef]] = {
val p = RPerson.as("p")
val c = RContact.as("c")
@ -162,7 +162,7 @@ object RPerson {
def findAllRef(
coll: Ident,
nameQ: Option[String],
order: Table => Column[_]
order: Table => Nel[OrderBy]
): ConnectionIO[Vector[IdRef]] = {
val nameFilter = nameQ.map(s => T.name.like(s"%${s.toLowerCase}%"))
@ -176,7 +176,7 @@ object RPerson {
DML.delete(T, T.pid === personId && T.cid === coll)
def findOrganization(ids: Set[Ident]): ConnectionIO[Vector[PersonRef]] =
NonEmptyList.fromList(ids.toList) match {
Nel.fromList(ids.toList) match {
case Some(nel) =>
run(select(T.pid, T.name, T.oid), from(T), T.pid.in(nel))
.query[PersonRef]

View File

@ -75,10 +75,11 @@ object RTag {
def findAll(
coll: Ident,
nameQ: Option[String],
order: Table => Column[_]
query: Option[String],
order: Table => NonEmptyList[OrderBy]
): ConnectionIO[Vector[RTag]] = {
val nameFilter = nameQ.map(s => T.name.like(s"%${s.toLowerCase}%"))
val nameFilter =
query.map(_.toLowerCase).map(s => T.name.like(s"%$s%") || T.category.like(s"%$s%"))
val sql =
Select(select(T.all), from(T), T.cid === coll &&? nameFilter).orderBy(order(T))
sql.build.query[RTag].to[Vector]