Skip to content

Commit 36df327

Browse files
NPCRUSnpcrusde
andauthored
Add OnConflict to InsertValues (#61)
Fixes #50 Fixed `Returning.InsertBase[V[Expr]]` into `Returning.InsertBase[V[Column]]`, looks like an oversight, this basically enabled me to write an implicit in `OnConflictOps` that made this fix possible @lihaoyi I'm not sure how to organize tests in this case, I hope you could have an idea, because current `OnConflictTests` are based on functionality and they don't distinguish between internal implementation of two different insert modes: `InsertValues` and `InsertColumns`, I could have just duplicated the tests with `.insert.values(???)`, but it doesn't seem right. Another question is that there are kinda missing tests for `InsertSelect` and then conflicts, do you want me to add those or was it intentional to not have them? --------- Co-authored-by: nikitaglushchenko <[email protected]>
1 parent 87c730b commit 36df327

File tree

4 files changed

+335
-9
lines changed

4 files changed

+335
-9
lines changed

docs/reference.md

Lines changed: 200 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4556,6 +4556,37 @@ Buyer.insert
45564556
45574557
45584558
4559+
----
4560+
4561+
with `insert.values`
4562+
4563+
```scala
4564+
Buyer.insert
4565+
.values(
4566+
Buyer[Sc](
4567+
id = 1,
4568+
name = "test buyer",
4569+
dateOfBirth = LocalDate.parse("2023-09-09")
4570+
)
4571+
)
4572+
.onConflictIgnore(_.id)
4573+
```
4574+
4575+
4576+
*
4577+
```sql
4578+
INSERT INTO buyer (id, name, date_of_birth) VALUES (?, ?, ?) ON CONFLICT (id) DO NOTHING
4579+
```
4580+
4581+
4582+
4583+
*
4584+
```scala
4585+
0
4586+
```
4587+
4588+
4589+
45594590
### OnConflict.ignore.returningEmpty
45604591
45614592
@@ -4588,6 +4619,40 @@ Buyer.insert
45884619
45894620
45904621
4622+
----
4623+
4624+
with `insert.values`
4625+
4626+
```scala
4627+
Buyer.insert
4628+
.values(
4629+
Buyer[Sc](
4630+
id = 1,
4631+
name = "test buyer",
4632+
dateOfBirth = LocalDate.parse("2023-09-09")
4633+
)
4634+
)
4635+
.onConflictIgnore(_.id)
4636+
.returning(_.name)
4637+
```
4638+
4639+
4640+
*
4641+
```sql
4642+
INSERT INTO buyer (id, name, date_of_birth) VALUES (?, ?, ?)
4643+
ON CONFLICT (id) DO NOTHING
4644+
RETURNING buyer.name AS res
4645+
```
4646+
4647+
4648+
4649+
*
4650+
```scala
4651+
Seq.empty[String]
4652+
```
4653+
4654+
4655+
45914656
### OnConflict.ignore.returningOne
45924657
45934658
@@ -4597,7 +4662,7 @@ Buyer.insert
45974662
.columns(
45984663
_.name := "test buyer",
45994664
_.dateOfBirth := LocalDate.parse("2023-09-09"),
4600-
_.id := 4 // This should cause a primary key conflict
4665+
_.id := 4
46014666
)
46024667
.onConflictIgnore(_.id)
46034668
.returning(_.name)
@@ -4620,6 +4685,40 @@ Buyer.insert
46204685
46214686
46224687
4688+
----
4689+
4690+
with `insert.values`
4691+
4692+
```scala
4693+
Buyer.insert
4694+
.values(
4695+
Buyer[Sc](
4696+
id = 5,
4697+
name = "test buyer",
4698+
dateOfBirth = LocalDate.parse("2023-09-09")
4699+
)
4700+
)
4701+
.onConflictIgnore(_.id)
4702+
.returning(_.name)
4703+
```
4704+
4705+
4706+
*
4707+
```sql
4708+
INSERT INTO buyer (id, name, date_of_birth) VALUES (?, ?, ?)
4709+
ON CONFLICT (id) DO NOTHING
4710+
RETURNING buyer.name AS res
4711+
```
4712+
4713+
4714+
4715+
*
4716+
```scala
4717+
Seq("test buyer")
4718+
```
4719+
4720+
4721+
46234722
### OnConflict.update
46244723
46254724
ScalaSql's `.onConflictUpdate` translates into SQL's `ON CONFLICT DO UPDATE`
@@ -4649,6 +4748,37 @@ Buyer.insert
46494748
46504749
46514750
4751+
----
4752+
4753+
with `insert.values`
4754+
4755+
```scala
4756+
Buyer.insert
4757+
.values(
4758+
Buyer[Sc](
4759+
id = 1,
4760+
name = "test buyer",
4761+
dateOfBirth = LocalDate.parse("2023-09-09")
4762+
)
4763+
)
4764+
.onConflictUpdate(_.id)(_.dateOfBirth := LocalDate.parse("2023-10-10"))
4765+
```
4766+
4767+
4768+
*
4769+
```sql
4770+
INSERT INTO buyer (id, name, date_of_birth) VALUES (?, ?, ?) ON CONFLICT (id) DO UPDATE SET date_of_birth = ?
4771+
```
4772+
4773+
4774+
4775+
*
4776+
```scala
4777+
1
4778+
```
4779+
4780+
4781+
46524782
----
46534783
46544784
@@ -4663,7 +4793,7 @@ Buyer.select
46634793
*
46644794
```scala
46654795
Seq(
4666-
Buyer[Sc](1, "TEST BUYER CONFLICT", LocalDate.parse("2001-02-03")),
4796+
Buyer[Sc](1, "TEST BUYER CONFLICT", LocalDate.parse("2023-10-10")),
46674797
Buyer[Sc](2, "叉烧包", LocalDate.parse("1923-11-12")),
46684798
Buyer[Sc](3, "Li Haoyi", LocalDate.parse("1965-08-09"))
46694799
)
@@ -4700,6 +4830,37 @@ Buyer.insert
47004830
47014831
47024832
4833+
----
4834+
4835+
with `insert.values`
4836+
4837+
```scala
4838+
Buyer.insert
4839+
.values(
4840+
Buyer[Sc](
4841+
id = 3,
4842+
name = "test buyer",
4843+
dateOfBirth = LocalDate.parse("2023-09-09")
4844+
)
4845+
)
4846+
.onConflictUpdate(_.id)(v => v.name := v.name.toUpperCase)
4847+
```
4848+
4849+
4850+
*
4851+
```sql
4852+
INSERT INTO buyer (id, name, date_of_birth) VALUES (?, ?, ?) ON CONFLICT (id) DO UPDATE SET name = UPPER(buyer.name)
4853+
```
4854+
4855+
4856+
4857+
*
4858+
```scala
4859+
1
4860+
```
4861+
4862+
4863+
47034864
----
47044865
47054866
@@ -4716,7 +4877,7 @@ Buyer.select
47164877
Seq(
47174878
Buyer[Sc](1, "JAMES BOND", LocalDate.parse("2001-02-03")),
47184879
Buyer[Sc](2, "叉烧包", LocalDate.parse("1923-11-12")),
4719-
Buyer[Sc](3, "Li Haoyi", LocalDate.parse("1965-08-09"))
4880+
Buyer[Sc](3, "LI HAOYI", LocalDate.parse("1965-08-09"))
47204881
)
47214882
```
47224883
@@ -4756,6 +4917,42 @@ Buyer.insert
47564917
47574918
47584919
4920+
----
4921+
4922+
with `insert.values`
4923+
4924+
```scala
4925+
Buyer.insert
4926+
.values(
4927+
Buyer[Sc](
4928+
id = 1,
4929+
name = "test buyer",
4930+
dateOfBirth = LocalDate.parse("2023-09-09")
4931+
)
4932+
)
4933+
.onConflictUpdate(_.id)(v => v.name := v.name.toLowerCase)
4934+
.returning(_.name)
4935+
.single
4936+
```
4937+
4938+
4939+
*
4940+
```sql
4941+
INSERT INTO buyer (id, name, date_of_birth) VALUES (?, ?, ?)
4942+
ON CONFLICT (id) DO UPDATE
4943+
SET name = LOWER(buyer.name)
4944+
RETURNING buyer.name AS res
4945+
```
4946+
4947+
4948+
4949+
*
4950+
```scala
4951+
"james bond"
4952+
```
4953+
4954+
4955+
47594956
## Values
47604957
Basic `VALUES` operations
47614958
### Values.basic

scalasql/query/src/InsertValues.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ package scalasql.query
33
import scalasql.core.{Context, DialectTypeMappers, Expr, Queryable, SqlStr, WithSqlExpr}
44
import scalasql.core.SqlStr.SqlStringSyntax
55

6-
trait InsertValues[V[_[_]], R] extends Returning.InsertBase[V[Expr]] with Query.ExecuteUpdate[Int] {
6+
trait InsertValues[V[_[_]], R]
7+
extends Returning.InsertBase[V[Column]]
8+
with Query.ExecuteUpdate[Int] {
79
def skipColumns(x: (V[Column] => Column[?])*): InsertValues[V, R]
810
}
911
object InsertValues {
@@ -16,7 +18,7 @@ object InsertValues {
1618
) extends InsertValues[V, R] {
1719

1820
def table = insert.table
19-
protected def expr = WithSqlExpr.get(insert).asInstanceOf[V[Expr]]
21+
protected def expr: V[Column] = WithSqlExpr.get(insert)
2022
override protected def queryConstruct(args: Queryable.ResultSetIterator): Int =
2123
args.get(dialect.IntType)
2224

scalasql/src/dialects/OnConflictOps.scala

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,16 @@ import scalasql.core.{Expr, WithSqlExpr}
44
import scalasql.query._
55

66
trait OnConflictOps {
7-
implicit def OnConflictableInsertValues[V[_[_]], R](
7+
implicit def OnConflictableInsertColumns[V[_[_]], R](
88
query: InsertColumns[V, R]
99
): OnConflict[V[Column], Int] =
1010
new OnConflict[V[Column], Int](query, WithSqlExpr.get(query), query.table)
1111

12+
implicit def OnConflictableInsertValues[V[_[_]], R](
13+
query: InsertValues[V, R]
14+
): OnConflict[V[Column], Int] =
15+
new OnConflict[V[Column], Int](query, WithSqlExpr.get(query), query.table)
16+
1217
implicit def OnConflictableInsertSelect[V[_[_]], C, R, R2](
1318
query: InsertSelect[V, C, R, R2]
1419
): OnConflict[V[Expr], Int] = {

0 commit comments

Comments
 (0)