diff --git a/src/main/scala/minisql/Meta.scala b/src/main/scala/minisql/Meta.scala index d7c5464..7f302ce 100644 --- a/src/main/scala/minisql/Meta.scala +++ b/src/main/scala/minisql/Meta.scala @@ -16,3 +16,16 @@ object UpdateMeta { inline def unsafe[E](inline ex: List[String]): UpdateMeta[E] = ex } + +opaque type InsertMeta[E] <: List[String] = List[String] + +object InsertMeta { + + inline def noExclude[E]: InsertMeta[E] = unsafe(Nil) + + inline def apply[E](using m: Mirror.ProductOf[E])( + inline exclude: List[Tuple.Union[m.MirroredElemLabels] & String] + ): InsertMeta[E] = unsafe(exclude) + + inline def unsafe[E](inline ex: List[String]): InsertMeta[E] = ex +} diff --git a/src/main/scala/minisql/Quoted.scala b/src/main/scala/minisql/Quoted.scala index 0f16d93..37fd684 100644 --- a/src/main/scala/minisql/Quoted.scala +++ b/src/main/scala/minisql/Quoted.scala @@ -165,8 +165,14 @@ object EntityQuery { transform(e)(f)(Filter.apply) } - inline def insert(v: E): Insert[E] = { - ast.Insert(e, transformCaseClassToAssignments[E](v, Nil)) + inline def insert( + v: E + )(using inline m: InsertMeta[E] = InsertMeta.noExclude[E]): Insert[E] = { + ast.Insert(e, transformCaseClassToAssignments[E](v, m)) + } + + inline def insert(inline ass: (E => (Any, Any))*): Insert[Long] = { + ast.Insert(e, parseFuncAssign(ass)) } inline def update( diff --git a/src/test/scala/minisql/context/sql/MirrorSqlContextSuite.scala b/src/test/scala/minisql/context/sql/MirrorSqlContextSuite.scala index ee320c3..4781e91 100644 --- a/src/test/scala/minisql/context/sql/MirrorSqlContextSuite.scala +++ b/src/test/scala/minisql/context/sql/MirrorSqlContextSuite.scala @@ -30,7 +30,7 @@ class MirrorSqlContextSuite extends munit.FunSuite { ) } - test("Insert") { + test("Insert - basic") { val v: Foo = Foo(0L, "foo", 1) val o = testContext.io(Foos.insert(v)) @@ -40,6 +40,47 @@ class MirrorSqlContextSuite extends munit.FunSuite { ) } + test("Insert - with excluded fields") { + inline given InsertMeta[Foo] = InsertMeta[Foo](List("age")) + + val v: Foo = Foo(0L, "foo", 1) + + val o = testContext.io(Foos.insert(v)) + assertEquals( + o.sql, + "INSERT INTO foo (id,name) VALUES (?, ?)" + ) + } + + test("Insert - with explicit assignments") { + val name = "test" + val age = 42 + + val o = testContext.io( + Foos.insert( + f => f.name -> lift(name), + f => f.age -> lift(age) + ) + ) + assertEquals( + o.sql, + "INSERT INTO foo (name,age) VALUES (?, ?)" + ) + } + + test("Insert - with mixed explicit and excluded") { + given InsertMeta[Foo] = InsertMeta[Foo](List("id")) + val name = "test" + + val o = testContext.io( + Foos.insert(f => f.name -> lift(name)) + ) + assertEquals( + o.sql, + "INSERT INTO foo (name) VALUES (?)" + ) + } + test("InsertReturningGenerated") { val o = testContext.io(Foos.insert(foo0).returningGenerated(_.id))