Merge pull request #1815 from eikek/fix/attach-count-query

Remove `attach.count` from query
This commit is contained in:
mergify[bot]
2022-10-31 21:37:07 +00:00
committed by GitHub
14 changed files with 2885 additions and 104 deletions

View File

@ -8,7 +8,7 @@ package docspell.query
import cats.data.{NonEmptyList => Nel} import cats.data.{NonEmptyList => Nel}
import docspell.query.ItemQuery.Attr.{DateAttr, IntAttr, StringAttr} import docspell.query.ItemQuery.Attr.{DateAttr, StringAttr}
/** A query evaluates to `true` or `false` given enough details about an item. /** A query evaluates to `true` or `false` given enough details about an item.
* *
@ -43,7 +43,7 @@ object ItemQuery {
object Attr { object Attr {
sealed trait StringAttr extends Attr sealed trait StringAttr extends Attr
sealed trait DateAttr extends Attr sealed trait DateAttr extends Attr
sealed trait IntAttr extends Attr // sealed trait IntAttr extends Attr
case object ItemName extends StringAttr case object ItemName extends StringAttr
case object ItemSource extends StringAttr case object ItemSource extends StringAttr
@ -52,7 +52,6 @@ object ItemQuery {
case object Date extends DateAttr case object Date extends DateAttr
case object DueDate extends DateAttr case object DueDate extends DateAttr
case object CreatedDate extends DateAttr case object CreatedDate extends DateAttr
case object AttachCount extends IntAttr
object Correspondent { object Correspondent {
case object OrgId extends StringAttr case object OrgId extends StringAttr
@ -78,7 +77,7 @@ object ItemQuery {
object Property { object Property {
final case class StringProperty(attr: StringAttr, value: String) extends Property final case class StringProperty(attr: StringAttr, value: String) extends Property
final case class DateProperty(attr: DateAttr, value: Date) extends Property final case class DateProperty(attr: DateAttr, value: Date) extends Property
final case class IntProperty(attr: IntAttr, value: Int) extends Property // final case class IntProperty(attr: IntAttr, value: Int) extends Property
def apply(sa: StringAttr, value: String): Property = def apply(sa: StringAttr, value: String): Property =
StringProperty(sa, value) StringProperty(sa, value)
@ -86,8 +85,8 @@ object ItemQuery {
def apply(da: DateAttr, value: Date): Property = def apply(da: DateAttr, value: Date): Property =
DateProperty(da, value) DateProperty(da, value)
def apply(na: IntAttr, value: Int): Property = // def apply(na: IntAttr, value: Int): Property =
IntProperty(na, value) // IntProperty(na, value)
} }
sealed trait Expr { sealed trait Expr {

View File

@ -72,14 +72,8 @@ object AttrParser {
val folderName: P[Attr.StringAttr] = val folderName: P[Attr.StringAttr] =
P.ignoreCase(C.folder).as(Attr.Folder.FolderName) P.ignoreCase(C.folder).as(Attr.Folder.FolderName)
val attachCountAttr: P[Attr.IntAttr] =
P.ignoreCase(C.attachCount).as(Attr.AttachCount)
// combining grouped by type // combining grouped by type
val intAttr: P[Attr.IntAttr] =
attachCountAttr
val dateAttr: P[Attr.DateAttr] = val dateAttr: P[Attr.DateAttr] =
P.oneOf(List(date, dueDate, created)) P.oneOf(List(date, dueDate, created))
@ -104,5 +98,5 @@ object AttrParser {
) )
val anyAttr: P[Attr] = val anyAttr: P[Attr] =
P.oneOf(List(dateAttr, stringAttr, intAttr)) P.oneOf(List(dateAttr, stringAttr))
} }

View File

@ -8,7 +8,7 @@ package docspell.query.internal
object Constants { object Constants {
val attachCount = "attach.count" // val attachCount = "attach.count"
val attachId = "attach.id" val attachId = "attach.id"
val cat = "cat" val cat = "cat"
val checksum = "checksum" val checksum = "checksum"

View File

@ -83,8 +83,8 @@ object ExprString {
Right(s"${stringAttr(attr)}${opStr(op)}${quote(value)}") Right(s"${stringAttr(attr)}${opStr(op)}${quote(value)}")
case Property.DateProperty(attr, value) => case Property.DateProperty(attr, value) =>
Right(s"${dateAttr(attr)}${opStr(op)}${dateStr(value)}") Right(s"${dateAttr(attr)}${opStr(op)}${dateStr(value)}")
case Property.IntProperty(attr, value) => // case Property.IntProperty(attr, value) =>
Right(s"${attrStr(attr)}${opStr(op)}$value") // Right(s"${attrStr(attr)}${opStr(op)}$value")
} }
case TagCategoryMatch(op, values) => case TagCategoryMatch(op, values) =>
@ -171,13 +171,6 @@ object ExprString {
attr match { attr match {
case a: StringAttr => stringAttr(a) case a: StringAttr => stringAttr(a)
case a: DateAttr => dateAttr(a) case a: DateAttr => dateAttr(a)
case a: IntAttr => intAttr(a)
}
private[internal] def intAttr(attr: IntAttr): String =
attr match {
case AttachCount =>
Constants.attachCount
} }
private[internal] def dateAttr(attr: DateAttr): String = private[internal] def dateAttr(attr: DateAttr): String =

View File

@ -6,7 +6,6 @@
package docspell.query.internal package docspell.query.internal
import cats.parse.Numbers
import cats.parse.{Parser => P} import cats.parse.{Parser => P}
import docspell.query.ItemQuery._ import docspell.query.ItemQuery._
@ -26,9 +25,6 @@ object SimpleExprParser {
private[this] val inOrOpDate = private[this] val inOrOpDate =
P.eitherOr(op ~ DateParser.date, inOp *> DateParser.dateOrMore) P.eitherOr(op ~ DateParser.date, inOp *> DateParser.dateOrMore)
private[this] val opInt =
op ~ Numbers.digits.map(_.toInt)
val stringExpr: P[Expr] = val stringExpr: P[Expr] =
(AttrParser.stringAttr ~ inOrOpStr).map { (AttrParser.stringAttr ~ inOrOpStr).map {
case (attr, Right((op, value))) => case (attr, Right((op, value))) =>
@ -45,11 +41,6 @@ object SimpleExprParser {
Expr.InDateExpr(attr, values) 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] = val existsExpr: P[Expr.Exists] =
(P.ignoreCase(C.exist) *> P.char(C.like) *> AttrParser.anyAttr).map(attr => (P.ignoreCase(C.exist) *> P.char(C.like) *> AttrParser.anyAttr).map(attr =>
Expr.Exists(attr) Expr.Exists(attr)
@ -114,7 +105,6 @@ object SimpleExprParser {
List( List(
dateExpr, dateExpr,
stringExpr, stringExpr,
intExpr,
existsExpr, existsExpr,
fulltextExpr, fulltextExpr,
tagIdExpr, tagIdExpr,

View File

@ -93,11 +93,8 @@ object ItemQueryGen {
val dateAttrGen: Gen[Attr.DateAttr] = val dateAttrGen: Gen[Attr.DateAttr] =
Gen.oneOf(Attr.Date, Attr.DueDate, Attr.CreatedDate) Gen.oneOf(Attr.Date, Attr.DueDate, Attr.CreatedDate)
val intAttrGen: Gen[Attr.IntAttr] =
Gen.const(Attr.AttachCount)
val attrGen: Gen[Attr] = val attrGen: Gen[Attr] =
Gen.oneOf(stringAttrGen, dateAttrGen, intAttrGen) Gen.oneOf(stringAttrGen, dateAttrGen)
private val valueChars = private val valueChars =
Gen.oneOf(Gen.alphaNumChar, Gen.oneOf(" /{}*?-:@#$~+%…_[]^!ß")) Gen.oneOf(Gen.alphaNumChar, Gen.oneOf(" /{}*?-:@#$~+%…_[]^!ß"))
@ -105,9 +102,6 @@ object ItemQueryGen {
private val stringValueGen: Gen[String] = private val stringValueGen: Gen[String] =
Gen.choose(1, 20).flatMap(n => Gen.stringOfN(n, valueChars)) Gen.choose(1, 20).flatMap(n => Gen.stringOfN(n, valueChars))
private val intValueGen: Gen[Int] =
Gen.choose(1900, 9999)
private val identGen: Gen[String] = private val identGen: Gen[String] =
Gen Gen
.choose(3, 12) .choose(3, 12)
@ -167,12 +161,6 @@ object ItemQueryGen {
sval <- stringValueGen sval <- stringValueGen
} yield Property.StringProperty(attr, sval) } yield Property.StringProperty(attr, sval)
val intPropGen: Gen[Property.IntProperty] =
for {
attr <- intAttrGen
ival <- intValueGen
} yield Property.IntProperty(attr, ival)
val datePropGen: Gen[Property.DateProperty] = val datePropGen: Gen[Property.DateProperty] =
for { for {
attr <- dateAttrGen attr <- dateAttrGen
@ -180,7 +168,7 @@ object ItemQueryGen {
} yield Property.DateProperty(attr, dv) } yield Property.DateProperty(attr, dv)
val propertyGen: Gen[Property] = val propertyGen: Gen[Property] =
Gen.oneOf(stringPropGen, datePropGen, intPropGen) Gen.oneOf(stringPropGen, datePropGen)
val simpleExprGen: Gen[Expr.SimpleExpr] = val simpleExprGen: Gen[Expr.SimpleExpr] =
for { for {

View File

@ -100,10 +100,6 @@ object ItemQueryGenerator {
val noLikeOp = if (op == Operator.Like) Operator.Eq else op val noLikeOp = if (op == Operator.Like) Operator.Eq else op
Condition.CompareFVal(col, makeOp(noLikeOp), dt) Condition.CompareFVal(col, makeOp(noLikeOp), dt)
case Expr.SimpleExpr(op, Property.IntProperty(attr, value)) =>
val col = intColumn(tables)(attr)
Condition.CompareVal(col, makeOp(op), value)
case Expr.InExpr(attr, values) => case Expr.InExpr(attr, values) =>
val col = stringColumn(tables)(attr) val col = stringColumn(tables)(attr)
if (values.tail.isEmpty) col === values.head if (values.tail.isEmpty) col === values.head
@ -228,8 +224,6 @@ object ItemQueryGenerator {
stringColumn(tables)(s).s stringColumn(tables)(s).s
case t: Attr.DateAttr => case t: Attr.DateAttr =>
timestampColumn(tables)(t) timestampColumn(tables)(t)
case n: Attr.IntAttr =>
intColumn(tables)(n).s
} }
private def timestampColumn(tables: Tables)(attr: Attr.DateAttr): SelectExpr = private def timestampColumn(tables: Tables)(attr: Attr.DateAttr): SelectExpr =
@ -260,11 +254,6 @@ object ItemQueryGenerator {
case Attr.Folder.FolderName => tables.folder.name case Attr.Folder.FolderName => tables.folder.name
} }
private def intColumn(tables: Tables)(attr: Attr.IntAttr): Column[Int] =
attr match {
case Attr.AttachCount => tables.attachCount.num
}
private def makeOp(operator: Operator): QOp = private def makeOp(operator: Operator): QOp =
operator match { operator match {
case Operator.Eq => case Operator.Eq =>

View File

@ -6,7 +6,6 @@
package docspell.store.qb.generator package docspell.store.qb.generator
import docspell.store.queries.AttachCountTable
import docspell.store.records._ import docspell.store.records._
final case class Tables( final case class Tables(
@ -17,6 +16,5 @@ final case class Tables(
concEquip: REquipment.Table, concEquip: REquipment.Table,
folder: RFolder.Table, folder: RFolder.Table,
attach: RAttachment.Table, attach: RAttachment.Table,
meta: RAttachmentMeta.Table, meta: RAttachmentMeta.Table
attachCount: AttachCountTable
) )

View File

@ -1,22 +0,0 @@
/*
* Copyright 2020 Eike K. & Contributors
*
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package docspell.store.queries
import docspell.common.Ident
import docspell.store.qb.Column
import docspell.store.qb.TableDef
final case class AttachCountTable(aliasName: String) extends TableDef {
val tableName = "attachs"
val alias: Option[String] = Some(aliasName)
val num = Column[Int]("num", this)
val itemId = Column[Ident]("item_id", this)
def as(alias: String): AttachCountTable =
copy(aliasName = alias)
}

View File

@ -299,7 +299,7 @@ object QItem extends FtsSupport {
coll: CollectiveId, coll: CollectiveId,
q: ItemQuery.Expr q: ItemQuery.Expr
): Condition = { ): Condition = {
val tables = Tables(i, org, pers0, pers1, equip, f, a, m, AttachCountTable("cta")) val tables = Tables(i, org, pers0, pers1, equip, f, a, m)
ItemQueryGenerator.fromExpr(today, tables, coll)(q) ItemQueryGenerator.fromExpr(today, tables, coll)(q)
} }

View File

@ -13,7 +13,6 @@ import docspell.query.ItemQueryParser
import docspell.store.qb.DSL._ import docspell.store.qb.DSL._
import docspell.store.qb.Select import docspell.store.qb.Select
import docspell.store.qb.generator.{ItemQueryGenerator, Tables} import docspell.store.qb.generator.{ItemQueryGenerator, Tables}
import docspell.store.queries.AttachCountTable
import docspell.store.records._ import docspell.store.records._
import munit._ import munit._
@ -29,8 +28,7 @@ class ItemQueryGeneratorTest extends FunSuite {
REquipment.as("ne"), REquipment.as("ne"),
RFolder.as("f"), RFolder.as("f"),
RAttachment.as("a"), RAttachment.as("a"),
RAttachmentMeta.as("m"), RAttachmentMeta.as("m")
AttachCountTable("cta")
) )
val now: LocalDate = LocalDate.of(2021, 2, 25) val now: LocalDate = LocalDate.of(2021, 2, 25)

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,6 @@
"name": "docspell-css", "name": "docspell-css",
"version": "1.0.0", "version": "1.0.0",
"private": true, "private": true,
"dependencies": {},
"devDependencies": { "devDependencies": {
"@fortawesome/fontawesome-free": "^6.0.0", "@fortawesome/fontawesome-free": "^6.0.0",
"@tailwindcss/forms": "^0.5.0", "@tailwindcss/forms": "^0.5.0",

View File

@ -91,7 +91,6 @@ These fields map to at most one value:
- `date` the item date - `date` the item date
- `due` the due date of the item - `due` the due date of the item
- `created` the date when the item was created - `created` the date when the item was created
- `attach.count` the number of attachments of the item
- `corr.org.id` the id of the correspondent organization - `corr.org.id` the id of the correspondent organization
- `corr.org.name` the name of the correspondent organization - `corr.org.name` the name of the correspondent organization
- `corr.pers.name` name of correspondent person - `corr.pers.name` name of correspondent person
@ -522,11 +521,6 @@ look into correspondent names and concerning names.
# Examples # Examples
Find items with 2 or more attachments:
```
attach.count>2
```
Find items with at least one tag invoice or todo that are due next: Find items with at least one tag invoice or todo that are due next:
``` ```
tag:invoice,todo due>today tag:invoice,todo due>today