diff --git a/modules/store/src/main/resources/db/migration/h2/V1.10.0__attachment_preview.sql b/modules/store/src/main/resources/db/migration/h2/V1.10.0__attachment_preview.sql new file mode 100644 index 00000000..c6b36cbe --- /dev/null +++ b/modules/store/src/main/resources/db/migration/h2/V1.10.0__attachment_preview.sql @@ -0,0 +1,8 @@ +CREATE TABLE "attachment_preview" ( + "id" varchar(254) not null primary key, + "file_id" varchar(254) not null, + "filename" varchar(254), + "created" timestamp not null, + foreign key ("file_id") references "filemeta"("id"), + foreign key ("id") references "attachment"("attachid") +); diff --git a/modules/store/src/main/resources/db/migration/mariadb/V1.10.0__attachment_preview.sql b/modules/store/src/main/resources/db/migration/mariadb/V1.10.0__attachment_preview.sql new file mode 100644 index 00000000..026a0c8c --- /dev/null +++ b/modules/store/src/main/resources/db/migration/mariadb/V1.10.0__attachment_preview.sql @@ -0,0 +1,8 @@ +CREATE TABLE `attachment_preview` ( + `id` varchar(254) not null primary key, + `file_id` varchar(254) not null, + `filename` varchar(254), + `created` timestamp not null, + foreign key (`file_id`) references `filemeta`(`id`), + foreign key (`id`) references `attachment`(`attachid`) +); diff --git a/modules/store/src/main/resources/db/migration/postgresql/V1.10.0__attachment_preview.sql b/modules/store/src/main/resources/db/migration/postgresql/V1.10.0__attachment_preview.sql new file mode 100644 index 00000000..c6b36cbe --- /dev/null +++ b/modules/store/src/main/resources/db/migration/postgresql/V1.10.0__attachment_preview.sql @@ -0,0 +1,8 @@ +CREATE TABLE "attachment_preview" ( + "id" varchar(254) not null primary key, + "file_id" varchar(254) not null, + "filename" varchar(254), + "created" timestamp not null, + foreign key ("file_id") references "filemeta"("id"), + foreign key ("id") references "attachment"("attachid") +); diff --git a/modules/store/src/main/scala/docspell/store/records/RAttachment.scala b/modules/store/src/main/scala/docspell/store/records/RAttachment.scala index 334ac711..4e8d3d40 100644 --- a/modules/store/src/main/scala/docspell/store/records/RAttachment.scala +++ b/modules/store/src/main/scala/docspell/store/records/RAttachment.scala @@ -224,8 +224,9 @@ object RAttachment { for { n0 <- RAttachmentMeta.delete(attachId) n1 <- RAttachmentSource.delete(attachId) - n2 <- deleteFrom(table, id.is(attachId)).update.run - } yield n0 + n1 + n2 + n2 <- RAttachmentPreview.delete(attachId) + n3 <- deleteFrom(table, id.is(attachId)).update.run + } yield n0 + n1 + n2 + n3 def findItemId(attachId: Ident): ConnectionIO[Option[Ident]] = selectSimple(Seq(itemId), table, id.is(attachId)).query[Ident].option diff --git a/modules/store/src/main/scala/docspell/store/records/RAttachmentPreview.scala b/modules/store/src/main/scala/docspell/store/records/RAttachmentPreview.scala new file mode 100644 index 00000000..65f1235b --- /dev/null +++ b/modules/store/src/main/scala/docspell/store/records/RAttachmentPreview.scala @@ -0,0 +1,98 @@ +package docspell.store.records + +import docspell.common._ +import docspell.store.impl.Implicits._ +import docspell.store.impl._ + +import bitpeace.FileMeta +import doobie._ +import doobie.implicits._ + +/** A preview image of an attachment. The `id` is shared with the + * attachment, to create a 1-1 (or 0..1-1) relationship. + */ +case class RAttachmentPreview( + id: Ident, //same as RAttachment.id + fileId: Ident, + name: Option[String], + created: Timestamp +) + +object RAttachmentPreview { + + val table = fr"attachment_preview" + + object Columns { + val id = Column("id") + val fileId = Column("file_id") + val name = Column("filename") + val created = Column("created") + + val all = List(id, fileId, name, created) + } + + import Columns._ + + def insert(v: RAttachmentPreview): ConnectionIO[Int] = + insertRow(table, all, fr"${v.id},${v.fileId},${v.name},${v.created}").update.run + + def findById(attachId: Ident): ConnectionIO[Option[RAttachmentPreview]] = + selectSimple(all, table, id.is(attachId)).query[RAttachmentPreview].option + + def delete(attachId: Ident): ConnectionIO[Int] = + deleteFrom(table, id.is(attachId)).update.run + + def findByIdAndCollective( + attachId: Ident, + collective: Ident + ): ConnectionIO[Option[RAttachmentPreview]] = { + val bId = RAttachment.Columns.id.prefix("b") + val aId = Columns.id.prefix("a") + val bItem = RAttachment.Columns.itemId.prefix("b") + val iId = RItem.Columns.id.prefix("i") + val iColl = RItem.Columns.cid.prefix("i") + + val from = table ++ fr"a INNER JOIN" ++ + RAttachment.table ++ fr"b ON" ++ aId.is(bId) ++ + fr"INNER JOIN" ++ RItem.table ++ fr"i ON" ++ bItem.is(iId) + + val where = and(aId.is(attachId), bId.is(attachId), iColl.is(collective)) + + selectSimple(all.map(_.prefix("a")), from, where).query[RAttachmentPreview].option + } + + def findByItem(itemId: Ident): ConnectionIO[Vector[RAttachmentPreview]] = { + val sId = Columns.id.prefix("s") + val aId = RAttachment.Columns.id.prefix("a") + val aItem = RAttachment.Columns.itemId.prefix("a") + + val from = table ++ fr"s INNER JOIN" ++ RAttachment.table ++ fr"a ON" ++ sId.is(aId) + selectSimple(all.map(_.prefix("s")), from, aItem.is(itemId)) + .query[RAttachmentPreview] + .to[Vector] + } + + def findByItemWithMeta( + id: Ident + ): ConnectionIO[Vector[(RAttachmentPreview, FileMeta)]] = { + import bitpeace.sql._ + + val aId = Columns.id.prefix("a") + val afileMeta = fileId.prefix("a") + val bPos = RAttachment.Columns.position.prefix("b") + val bId = RAttachment.Columns.id.prefix("b") + val bItem = RAttachment.Columns.itemId.prefix("b") + val mId = RFileMeta.Columns.id.prefix("m") + + val cols = all.map(_.prefix("a")) ++ RFileMeta.Columns.all.map(_.prefix("m")) + val from = table ++ fr"a INNER JOIN" ++ + RFileMeta.table ++ fr"m ON" ++ afileMeta.is(mId) ++ fr"INNER JOIN" ++ + RAttachment.table ++ fr"b ON" ++ aId.is(bId) + val where = bItem.is(id) + + (selectSimple(cols, from, where) ++ orderBy(bPos.asc)) + .query[(RAttachmentPreview, FileMeta)] + .to[Vector] + } + +}