Delete single attachments

This commit is contained in:
Eike Kettner
2020-04-26 23:04:03 +02:00
parent 916a9dbcc9
commit a939839041
11 changed files with 149 additions and 25 deletions

View File

@ -30,6 +30,9 @@ case class Column(name: String, ns: String = "", alias: String = "") {
def is(c: Column): Fragment =
f ++ fr"=" ++ c.f
def isSubquery(sq: Fragment): Fragment =
f ++ fr"=" ++ fr"(" ++ sq ++ fr")"
def isNot[A: Put](value: A): Fragment =
f ++ fr"<> $value"

View File

@ -15,28 +15,39 @@ import docspell.common.syntax.all._
object QAttachment {
private[this] val logger = org.log4s.getLogger
def deleteById[F[_]: Sync](store: Store[F])(attachId: Ident, coll: Ident): F[Int] =
/** Deletes an attachment, its related source and meta data records.
* It will only delete an related archive file, if this is the last
* attachment in that archive.
*/
def deleteSingleAttachment[F[_]: Sync](
store: Store[F]
)(attachId: Ident, coll: Ident): F[Int] = {
val loadFiles = for {
ra <- RAttachment.findByIdAndCollective(attachId, coll).map(_.map(_.fileId))
rs <- RAttachmentSource.findByIdAndCollective(attachId, coll).map(_.map(_.fileId))
ne <- RAttachmentArchive.countEntries(attachId)
} yield (ra, rs, ne)
for {
raFile <- store
.transact(RAttachment.findByIdAndCollective(attachId, coll))
.map(_.map(_.fileId))
rsFile <- store
.transact(RAttachmentSource.findByIdAndCollective(attachId, coll))
.map(_.map(_.fileId))
aaFile <- store
.transact(RAttachmentArchive.findByIdAndCollective(attachId, coll))
.map(_.map(_.fileId))
files <- store.transact(loadFiles)
k <- if (files._3 == 1) deleteArchive(store)(attachId)
else store.transact(RAttachmentArchive.delete(attachId))
n <- store.transact(RAttachment.delete(attachId))
f <- Stream
.emits(raFile.toSeq ++ rsFile.toSeq ++ aaFile.toSeq)
.emits(files._1.toSeq ++ files._2.toSeq)
.map(_.id)
.flatMap(store.bitpeace.delete)
.map(flag => if (flag) 1 else 0)
.compile
.foldMonoid
} yield n + f
} yield n + k + f
}
def deleteAttachment[F[_]: Sync](store: Store[F])(ra: RAttachment): F[Int] =
/** This deletes the attachment and *all* its related files. This used
* when deleting an item and should not be used to delete a
* *single* attachment where the item should stay.
*/
private def deleteAttachment[F[_]: Sync](store: Store[F])(ra: RAttachment): F[Int] =
for {
_ <- logger.fdebug[F](s"Deleting attachment: ${ra.id.id}")
s <- store.transact(RAttachmentSource.findById(ra.id))

View File

@ -124,6 +124,8 @@ object RAttachment {
q.query[(RAttachment, FileMeta)].to[Vector]
}
/** Deletes the attachment and its related source and meta records.
*/
def delete(attachId: Ident): ConnectionIO[Int] =
for {
n0 <- RAttachmentMeta.delete(attachId)

View File

@ -91,4 +91,13 @@ object RAttachmentArchive {
.to[Vector]
}
/** If the given attachment id has an associated archive, this returns
* the number of all associated attachments. Returns 0 if there is
* no archive for the given attachment.
*/
def countEntries(attachId: Ident): ConnectionIO[Int] = {
val qFileId = selectSimple(Seq(fileId), table, id.is(attachId))
val q = selectCount(id, table, fileId.isSubquery(qFileId))
q.query[Int].unique
}
}