diff --git a/modules/core/src/main/scala/doobie/util/fragments.scala b/modules/core/src/main/scala/doobie/util/fragments.scala index 2b6083e4a..cb567094d 100644 --- a/modules/core/src/main/scala/doobie/util/fragments.scala +++ b/modules/core/src/main/scala/doobie/util/fragments.scala @@ -9,6 +9,7 @@ import cats.data.NonEmptyList import cats.syntax.all.* import cats.{Foldable, Functor, Reducible} import doobie.implicits.* +import doobie.Fragment.* /** Module of `Fragment` constructors. */ object fragments { @@ -17,6 +18,14 @@ object fragments { def values[F[_]: Reducible, A](fs: F[A])(implicit w: util.Write[A]): Fragment = fr"VALUES" ++ comma(fs.toNonEmptyList.map(f => parentheses(values(f)))) + /** Returns `UPDATE tableName SET columnUpdate0, columnUpdate1, ...`. */ + def updateSetOpt[F[_]: Foldable]( + tableName: Fragment, + columnUpdates: F[Fragment] + ): Option[Fragment] = { + NonEmptyList.fromFoldable(columnUpdates).map(cs => fr"UPDATE" ++ tableName ++ set(cs)) + } + /** Returns `(f IN (fs0, fs1, ...))`. */ def in[A: util.Put](f: Fragment, fs0: A, fs1: A, fs: A*): Fragment = in(f, NonEmptyList(fs0, fs1 :: fs.toList)) diff --git a/modules/core/src/test/scala/doobie/util/FragmentsSuite.scala b/modules/core/src/test/scala/doobie/util/FragmentsSuite.scala index 68755325c..a642ac3af 100644 --- a/modules/core/src/test/scala/doobie/util/FragmentsSuite.scala +++ b/modules/core/src/test/scala/doobie/util/FragmentsSuite.scala @@ -28,6 +28,7 @@ class FragmentsSuite extends munit.FunSuite { val someF: Option[Fragment] = Some(sql"${1}") val noneF: Option[Fragment] = None val ofs = List(Some(sql"${1}"), None, Some(sql"${3}")) + val sqlKv = nelInt.zipWith(NonEmptyList.of("a", "b", "c"))((v, k) => fr0"${Fragment.const0(k)} = $v").toList test("values for one column") { assertEquals(values(nelInt).query[Unit].sql, "VALUES (?) , (?) , (?) ") @@ -37,6 +38,16 @@ class FragmentsSuite extends munit.FunSuite { assertEquals(values(NonEmptyList.of((1, true), (2, false))).query[Unit].sql, "VALUES (?,?) , (?,?) ") } + test("updateSetOpt for three column") { + assertEquals( + updateSetOpt(Fragment.const("Foo"), sqlKv).map(_.query[Unit].sql), + Some("UPDATE Foo SET a = ?, b = ?, c = ?")) + } + + test("updateSetOpt for empty columns") { + assertEquals(updateSetOpt(Fragment.const("Foo"), List.empty[Fragment]).map(_.query[Unit].sql), None) + } + test("in (1-column varargs)") { assertEquals(in(sql"foo", 1, 2, 3).query[Unit].sql, "(foo IN (? , ? , ? ) ) ") }