Ссылка на вопрос это.
Я хочу вставить какую-то сущность по какому-то условию. Его можно либо вставить, либо нет. Если условие истинно, сущность вставляется. Я хочу вставить некоторые другие данные в различные таблицы. Это выглядит так:
val q = sql"insert into some_table (some_field) select 42 where ...(some condition)"
val inserts = List(
sql"insert ...",
sql"insert ...",
sql"insert ..."
)
for {
id <- q.update.withGeneratedKeys[Long]("id")
_ <- inserts.reduce(_ ++ _).update.run
} yield id
Проблема в том, что это не компилируется, потому что первая вставка — это fs2.Stream, а вторая — нет.
Я пытался заменить _ <- inserts.reduce... на _ = inserts.reduce. Приложение может скомпилироваться, но inserts во второй строке не встречается.
УПД
Мой возможный способ решить эту проблему:
...
for {
idOpt <- q.update.withGeneratedKeys[Long]("id").compile.last
_ <- idOpt.fold(0.pure[ConnectionIO])(_ => inserts.reduce(_ ++ _).update.run)
} yield idOpt
Это работает, но ИМХО это некрасиво. Есть ли лучший способ сделать это?
@gekomad, к сожалению, на моем нынешнем рабочем месте забанен гиттер. Не знаю почему.





Один из способов выполнить пакетную вставку — если у вас есть похожие данные — использовать updateMany — см. документ:
import doobie._
type PersonInfo = (String, Option[Short])
def insertMany(ps: List[PersonInfo]): ConnectionIO[Int] = {
val sql = "insert into person (name, age) values (?, ?)"
Update[PersonInfo](sql).updateMany(ps)
}
// Some rows to insert
val data = List[PersonInfo](
("Frank", Some(12)),
("Daddy", None))
Кроме того, если вы удалите .compile.last, вы можете использовать тот факт, что если ваш результирующий Streamq.update.withGeneratedKeys[Long]("id") равен empty, вы «выходите раньше» из for-comprehension.
Итак, в общем, вот что вы можете сделать:
import fs2.Stream
val result =
// Now the for-comprehension operates on a Stream instead of an Option
for {
r <- q.update.withGeneratedKeys[Long]("id")
_ <- Stream.eval(insertMany(data)) // insertMany(data) is defined like in the snippet above
} yield r
result.compile.last
вы могли бы попросить, чтобы doobie gitter gitter.im/tpolecat/doobie