Add more ways to query for attachments

- find items with a specified attachment count
- find items by attachment id
This commit is contained in:
Eike Kettner
2021-03-08 09:30:47 +01:00
parent 2b2f913e85
commit 30c901ddf1
9 changed files with 89 additions and 25 deletions

View File

@ -2,7 +2,7 @@ package docspell.query
import cats.data.{NonEmptyList => Nel}
import docspell.query.ItemQuery.Attr.{DateAttr, StringAttr}
import docspell.query.ItemQuery.Attr.{DateAttr, IntAttr, StringAttr}
/** A query evaluates to `true` or `false` given enough details about
* an item.
@ -40,13 +40,15 @@ object ItemQuery {
object Attr {
sealed trait StringAttr extends Attr
sealed trait DateAttr extends Attr
sealed trait IntAttr extends Attr
case object ItemName extends StringAttr
case object ItemSource extends StringAttr
case object ItemNotes extends StringAttr
case object ItemId extends StringAttr
case object Date extends DateAttr
case object DueDate extends DateAttr
case object ItemName extends StringAttr
case object ItemSource extends StringAttr
case object ItemNotes extends StringAttr
case object ItemId extends StringAttr
case object Date extends DateAttr
case object DueDate extends DateAttr
case object AttachCount extends IntAttr
object Correspondent {
case object OrgId extends StringAttr
@ -72,12 +74,16 @@ object ItemQuery {
object Property {
final case class StringProperty(attr: StringAttr, value: String) extends Property
final case class DateProperty(attr: DateAttr, value: Date) extends Property
final case class IntProperty(attr: IntAttr, value: Int) extends Property
def apply(sa: StringAttr, value: String): Property =
StringProperty(sa, value)
def apply(da: DateAttr, value: Date): Property =
DateProperty(da, value)
def apply(na: IntAttr, value: Int): Property =
IntProperty(na, value)
}
sealed trait Expr {
@ -111,6 +117,7 @@ object ItemQuery {
final case class Fulltext(query: String) extends Expr
final case class ChecksumMatch(checksum: String) extends Expr
final case class AttachId(id: String) extends Expr
// things that can be expressed with terms above
sealed trait MacroExpr extends Expr {

View File

@ -62,6 +62,14 @@ object AttrParser {
val folderName: P[Attr.StringAttr] =
P.ignoreCase("folder").as(Attr.Folder.FolderName)
val attachCountAttr: P[Attr.IntAttr] =
P.ignoreCase("attach.count").as(Attr.AttachCount)
// combining grouped by type
val intAttr: P[Attr.IntAttr] =
attachCountAttr
val dateAttr: P[Attr.DateAttr] =
P.oneOf(List(date, dueDate))
@ -86,5 +94,5 @@ object AttrParser {
)
val anyAttr: P[Attr] =
P.oneOf(List(dateAttr, stringAttr))
P.oneOf(List(dateAttr, stringAttr, intAttr))
}

View File

@ -67,6 +67,8 @@ object ExprUtil {
expr
case ChecksumMatch(_) =>
expr
case AttachId(_) =>
expr
}
private def spliceAnd(nodes: Nel[Expr]): Nel[Expr] =

View File

@ -1,5 +1,6 @@
package docspell.query.internal
import cats.parse.Numbers
import cats.parse.{Parser => P}
import docspell.query.ItemQuery._
@ -18,6 +19,9 @@ object SimpleExprParser {
private[this] val inOrOpDate =
P.eitherOr(op ~ DateParser.date, inOp *> DateParser.dateOrMore)
private[this] val opInt =
op ~ Numbers.digits.map(_.toInt)
val stringExpr: P[Expr] =
(AttrParser.stringAttr ~ inOrOpStr).map {
case (attr, Right((op, value))) =>
@ -34,6 +38,11 @@ object SimpleExprParser {
Expr.InDateExpr(attr, values)
}
val intExpr: P[Expr] =
(AttrParser.intAttr ~ opInt).map { case (attr, (op, value)) =>
Expr.SimpleExpr(op, Property(attr, value))
}
val existsExpr: P[Expr.Exists] =
(P.ignoreCase("exists:") *> AttrParser.anyAttr).map(attr => Expr.Exists(attr))
@ -79,11 +88,15 @@ object SimpleExprParser {
val checksumExpr: P[Expr.ChecksumMatch] =
(P.string("checksum:") *> BasicParser.singleString).map(Expr.ChecksumMatch.apply)
val attachIdExpr: P[Expr.AttachId] =
(P.ignoreCase("attach.id:") *> BasicParser.singleString).map(Expr.AttachId.apply)
val simpleExpr: P[Expr] =
P.oneOf(
List(
dateExpr,
stringExpr,
intExpr,
existsExpr,
fulltextExpr,
tagIdExpr,
@ -93,7 +106,8 @@ object SimpleExprParser {
customFieldExpr,
inboxExpr,
dirExpr,
checksumExpr
checksumExpr,
attachIdExpr
)
)
}