diff --git a/modules/core/src/main/scala/doobie/util/write.scala b/modules/core/src/main/scala/doobie/util/write.scala index 1ca610cc5..325b4964f 100644 --- a/modules/core/src/main/scala/doobie/util/write.scala +++ b/modules/core/src/main/scala/doobie/util/write.scala @@ -112,11 +112,13 @@ sealed trait Write1 extends WritePlatform { this: Write.type => case o => Option(o) } } - override def unsafeSet(ps: PreparedStatement, i: Int, a: Option[A]) = { - a.foreach(W.unsafeSet(ps, i, _)) + override def unsafeSet(ps: PreparedStatement, i: Int, a: Option[A]) = a match { + case None => W.puts.zipWithIndex.foreach { case ((p, _), o) => p.unsafeSetNullable(ps, i + o, None) } + case Some(a) => W.unsafeSet(ps, i, a) } - override def unsafeUpdate(rs: ResultSet, i: Int, a: Option[A]) = { - a.foreach(W.unsafeUpdate(rs, i, _)) + override def unsafeUpdate(rs: ResultSet, i: Int, a: Option[A]) = a match { + case None => W.puts.zipWithIndex.foreach { case ((p, _), o) => p.unsafeUpdateNullable(rs, i + o, None) } + case Some(a) => W.unsafeUpdate(rs, i, a) } } } diff --git a/modules/core/src/test/scala/doobie/util/WriteSuite.scala b/modules/core/src/test/scala/doobie/util/WriteSuite.scala index 0dcdc1d99..5c4707355 100644 --- a/modules/core/src/test/scala/doobie/util/WriteSuite.scala +++ b/modules/core/src/test/scala/doobie/util/WriteSuite.scala @@ -121,6 +121,7 @@ object WriteSuite extends H2DatabaseSpec with WriteSuitePlatform { }, suite("write correctly")( test("fragment") { + def insert[A](a: A)(implicit W: Write[A]) = { fr"INSERT INTO test_write (v, s) VALUES ($a)".update.withUniqueGeneratedKeys[Test]("v", "s") } @@ -187,6 +188,30 @@ object WriteSuite extends H2DatabaseSpec with WriteSuitePlatform { } conn.transact }, + test("nested") { + + def insert(a: TestNested) = { + fr"INSERT INTO test_write_n (v, s) VALUES ($a)".update.withUniqueGeneratedKeys[TestNested]("v", "s") + } + + val conn = for { + _ <- Update0( + "CREATE LOCAL TEMPORARY TABLE IF NOT EXISTS test_write_n(v INT, s VARCHAR) NOT PERSISTENT", + None, + ).run + + t0 <- insert(TestNested(None)) + t1 <- insert(TestNested(Some(Test(None, None)))) + t2 <- insert(TestNested(Some(Test(None, Some("str"))))) + t3 <- insert(TestNested(Some(Test(Some(3), Some("str"))))) + } yield { + assertTrue(t0 == TestNested(None)) && + assertTrue(t1 == TestNested(None)) && + assertTrue(t2 == TestNested(Some(Test(None, Some("str"))))) && + assertTrue(t3 == TestNested(Some(Test(Some(3), Some("str"))))) + } + conn.transact + }, ), suite("platform specific")(platformTests*), ) @@ -198,4 +223,11 @@ object WriteSuite extends H2DatabaseSpec with WriteSuitePlatform { val writeTuple = (Write[Option[Int]], Write[Option[String]]).tupled } + case class TestNested(n: Option[Test]) + object TestNested { + implicit val read: Read[TestNested] = Read.derived + implicit val writeTest: Write[Test] = Test.write + implicit val write: Write[TestNested] = Write.derived + } + }