mirror of
https://github.com/TheAnachronism/docspell.git
synced 2025-06-06 15:15:58 +00:00
Add checksum query expr
This commit is contained in:
parent
7b1ec97c97
commit
2b2f913e85
@ -110,6 +110,7 @@ object ItemQuery {
|
|||||||
extends Expr
|
extends Expr
|
||||||
|
|
||||||
final case class Fulltext(query: String) extends Expr
|
final case class Fulltext(query: String) extends Expr
|
||||||
|
final case class ChecksumMatch(checksum: String) extends Expr
|
||||||
|
|
||||||
// things that can be expressed with terms above
|
// things that can be expressed with terms above
|
||||||
sealed trait MacroExpr extends Expr {
|
sealed trait MacroExpr extends Expr {
|
||||||
|
@ -65,6 +65,8 @@ object ExprUtil {
|
|||||||
expr
|
expr
|
||||||
case CustomFieldIdMatch(_, _, _) =>
|
case CustomFieldIdMatch(_, _, _) =>
|
||||||
expr
|
expr
|
||||||
|
case ChecksumMatch(_) =>
|
||||||
|
expr
|
||||||
}
|
}
|
||||||
|
|
||||||
private def spliceAnd(nodes: Nel[Expr]): Nel[Expr] =
|
private def spliceAnd(nodes: Nel[Expr]): Nel[Expr] =
|
||||||
|
@ -76,6 +76,9 @@ object SimpleExprParser {
|
|||||||
val dirExpr: P[Expr.DirectionExpr] =
|
val dirExpr: P[Expr.DirectionExpr] =
|
||||||
(P.string("incoming:") *> BasicParser.bool).map(Expr.DirectionExpr.apply)
|
(P.string("incoming:") *> BasicParser.bool).map(Expr.DirectionExpr.apply)
|
||||||
|
|
||||||
|
val checksumExpr: P[Expr.ChecksumMatch] =
|
||||||
|
(P.string("checksum:") *> BasicParser.singleString).map(Expr.ChecksumMatch.apply)
|
||||||
|
|
||||||
val simpleExpr: P[Expr] =
|
val simpleExpr: P[Expr] =
|
||||||
P.oneOf(
|
P.oneOf(
|
||||||
List(
|
List(
|
||||||
@ -89,7 +92,8 @@ object SimpleExprParser {
|
|||||||
customFieldIdExpr,
|
customFieldIdExpr,
|
||||||
customFieldExpr,
|
customFieldExpr,
|
||||||
inboxExpr,
|
inboxExpr,
|
||||||
dirExpr
|
dirExpr,
|
||||||
|
checksumExpr
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,16 @@ package docspell.store.qb.generator
|
|||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
import java.time.LocalDate
|
import java.time.LocalDate
|
||||||
|
|
||||||
import cats.data.NonEmptyList
|
import cats.data.{NonEmptyList => Nel}
|
||||||
|
|
||||||
import docspell.common._
|
import docspell.common._
|
||||||
import docspell.query.ItemQuery._
|
import docspell.query.ItemQuery._
|
||||||
import docspell.query.{Date, ItemQuery}
|
import docspell.query.{Date, ItemQuery}
|
||||||
import docspell.store.qb.DSL._
|
import docspell.store.qb.DSL._
|
||||||
import docspell.store.qb.{Operator => QOp, _}
|
import docspell.store.qb.{Operator => QOp, _}
|
||||||
|
import docspell.store.queries.QItem
|
||||||
import docspell.store.queries.QueryWildcard
|
import docspell.store.queries.QueryWildcard
|
||||||
import docspell.store.records.{RCustomField, RCustomFieldValue, TagItemName}
|
import docspell.store.records._
|
||||||
|
|
||||||
import doobie.util.Put
|
import doobie.util.Put
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ object ItemQueryGenerator {
|
|||||||
|
|
||||||
case Expr.TagIdsMatch(op, tags) =>
|
case Expr.TagIdsMatch(op, tags) =>
|
||||||
val ids = tags.toList.flatMap(s => Ident.fromString(s).toOption)
|
val ids = tags.toList.flatMap(s => Ident.fromString(s).toOption)
|
||||||
NonEmptyList
|
Nel
|
||||||
.fromList(ids)
|
.fromList(ids)
|
||||||
.map { nel =>
|
.map { nel =>
|
||||||
op match {
|
op match {
|
||||||
@ -114,7 +115,7 @@ object ItemQueryGenerator {
|
|||||||
|
|
||||||
case Expr.TagIdsMatch(op, tags) =>
|
case Expr.TagIdsMatch(op, tags) =>
|
||||||
val ids = tags.toList.flatMap(s => Ident.fromString(s).toOption)
|
val ids = tags.toList.flatMap(s => Ident.fromString(s).toOption)
|
||||||
NonEmptyList
|
Nel
|
||||||
.fromList(ids)
|
.fromList(ids)
|
||||||
.map { nel =>
|
.map { nel =>
|
||||||
op match {
|
op match {
|
||||||
@ -152,6 +153,10 @@ object ItemQueryGenerator {
|
|||||||
case Expr.CustomFieldIdMatch(field, op, value) =>
|
case Expr.CustomFieldIdMatch(field, op, value) =>
|
||||||
tables.item.id.in(itemsWithCustomField(_.id ==== field)(coll, makeOp(op), value))
|
tables.item.id.in(itemsWithCustomField(_.id ==== field)(coll, makeOp(op), value))
|
||||||
|
|
||||||
|
case Expr.ChecksumMatch(checksum) =>
|
||||||
|
val select = QItem.findByChecksumQuery(checksum, coll, Set.empty)
|
||||||
|
tables.item.id.in(select.withSelect(Nel.of(RItem.as("i").id.s)))
|
||||||
|
|
||||||
case Expr.Fulltext(_) =>
|
case Expr.Fulltext(_) =>
|
||||||
// not supported here
|
// not supported here
|
||||||
Condition.unit
|
Condition.unit
|
||||||
|
@ -509,6 +509,16 @@ object QItem {
|
|||||||
collective: Ident,
|
collective: Ident,
|
||||||
excludeFileMeta: Set[Ident]
|
excludeFileMeta: Set[Ident]
|
||||||
): ConnectionIO[Vector[RItem]] = {
|
): ConnectionIO[Vector[RItem]] = {
|
||||||
|
val qq = findByChecksumQuery(checksum, collective, excludeFileMeta).build
|
||||||
|
logger.debug(s"FindByChecksum: $qq")
|
||||||
|
qq.query[RItem].to[Vector]
|
||||||
|
}
|
||||||
|
|
||||||
|
def findByChecksumQuery(
|
||||||
|
checksum: String,
|
||||||
|
collective: Ident,
|
||||||
|
excludeFileMeta: Set[Ident]
|
||||||
|
): Select = {
|
||||||
val m1 = RFileMeta.as("m1")
|
val m1 = RFileMeta.as("m1")
|
||||||
val m2 = RFileMeta.as("m2")
|
val m2 = RFileMeta.as("m2")
|
||||||
val m3 = RFileMeta.as("m3")
|
val m3 = RFileMeta.as("m3")
|
||||||
@ -517,7 +527,6 @@ object QItem {
|
|||||||
val s = RAttachmentSource.as("s")
|
val s = RAttachmentSource.as("s")
|
||||||
val r = RAttachmentArchive.as("r")
|
val r = RAttachmentArchive.as("r")
|
||||||
val fms = Nel.of(m1, m2, m3)
|
val fms = Nel.of(m1, m2, m3)
|
||||||
val qq =
|
|
||||||
Select(
|
Select(
|
||||||
select(i.all),
|
select(i.all),
|
||||||
from(i)
|
from(i)
|
||||||
@ -534,9 +543,7 @@ object QItem {
|
|||||||
.fromList(excludeFileMeta.toList)
|
.fromList(excludeFileMeta.toList)
|
||||||
.map(excl => Condition.And(fms.map(m => m.id.isNull || m.id.notIn(excl))))
|
.map(excl => Condition.And(fms.map(m => m.id.isNull || m.id.notIn(excl))))
|
||||||
)
|
)
|
||||||
).distinct.build
|
).distinct
|
||||||
logger.debug(s"FindByChecksum: $qq")
|
|
||||||
qq.query[RItem].to[Vector]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final case class NameAndNotes(
|
final case class NameAndNotes(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user