Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mysql onconflict update with renames #2708

Merged
merged 4 commits into from Jul 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
16 changes: 16 additions & 0 deletions quill-core/src/test/scala/io/getquill/TestEntities.scala
Expand Up @@ -7,6 +7,22 @@ trait TestEntities {
this: Context[_, _] =>

case class TestEntity(s: String, i: Int, l: Long, o: Option[Int], b: Boolean)

lazy val testEntitySchemaMeta = schemaMeta[TestEntity](
"TestEntity",
_.s -> "s"
)

lazy val testEntityQuerySchema = quote(
querySchema[TestEntity](
"TestEntity",
_.s -> "s",
_.i -> "i",
_.l -> "l",
_.o -> "o",
_.b -> "b"
)
)
case class Emb(s: String, i: Int)
case class TestEntityEmb(emb: Emb, l: Long, o: Option[Int])
case class TestEntity2(s: String, i: Int, l: Long, o: Option[Int])
Expand Down
3 changes: 1 addition & 2 deletions quill-engine/src/main/scala/io/getquill/MySQLDialect.scala
Expand Up @@ -71,8 +71,7 @@ trait MySQLDialect
val customAstTokenizer =
Tokenizer.withFallback[Ast](MySQLDialect.this.astTokenizer(_, strategy, idiomContext)) {
case Property.Opinionated(Excluded(_), name, renameable, _) =>
renameable.fixedOr(name.token)(stmt"VALUES(${strategy.column(name).token})")

stmt"VALUES(${renameable.fixedOr(name.token)(strategy.column(name).token)})"
case Property.Opinionated(_, name, renameable, _) =>
renameable.fixedOr(name.token)(strategy.column(name).token)
}
Expand Down
Expand Up @@ -5,9 +5,9 @@ import io.getquill.{H2Dialect, Literal, SqlMirrorContext, TestEntities}
class H2DialectSpec extends OnConflictSpec {
val ctx = new SqlMirrorContext(H2Dialect, Literal) with TestEntities
import ctx._
"OnConflict" - {
"OnConflict" - `onConflict with all` { i =>
"no target - ignore" in {
ctx.run(`no target - ignore`).string mustEqual
ctx.run(`no target - ignore`(i)).string mustEqual
"INSERT INTO TestEntity (s,i,l,o,b) VALUES ($1, $2, $3, $4, $5) ON CONFLICT DO NOTHING"
}
"no target - ignore batch" in {
Expand Down
Expand Up @@ -95,23 +95,22 @@ class MySQLDialectSpec extends OnConflictSpec {
"ctx.run(q.returning(_.i)).string" mustNot compile
}

"OnConflict" - {
"OnConflict" - `onConflict with all` { i =>
"no target - ignore" in {
ctx.run(`no target - ignore`.dynamic).string mustEqual
ctx.run(`no target - ignore`(i).dynamic).string mustEqual
"INSERT IGNORE INTO TestEntity (s,i,l,o,b) VALUES (?, ?, ?, ?, ?)"

}
"cols target - ignore" in {
ctx.run(`cols target - ignore`.dynamic).string mustEqual
ctx.run(`cols target - ignore`(i).dynamic).string mustEqual
"INSERT INTO TestEntity (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE i=i"
}
"no target - update" in {
ctx.run(`no target - update`).string mustEqual
ctx.run(`no target - update`(i)).string mustEqual
"INSERT INTO TestEntity (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE l = ((l + VALUES(l)) / 2), s = VALUES(s)"
}
"cols target - update" in {
intercept[IllegalStateException] {
ctx.run(`cols target - update`.dynamic)
ctx.run(`cols target - update`(i).dynamic)
}
}
}
Expand Down
@@ -1,6 +1,6 @@
package io.getquill.context.sql.idiom

import io.getquill.TestEntities
import io.getquill.{Insert, Quoted, TestEntities}
import io.getquill.base.Spec
import io.getquill.context.sql.SqlContext

Expand All @@ -10,19 +10,34 @@ trait OnConflictSpec extends Spec {

lazy val e = TestEntity("s1", 1, 1, None, true)

def ins = quote(query[TestEntity].insertValue(lift(e)))
def `onConflict with query`(fun: Quoted[Insert[TestEntity]] => Unit) =
"with query" - fun(quote(query[TestEntity].insertValue(lift(e))))
def `onConflict with schemaMeta`(fun: Quoted[Insert[TestEntity]] => Unit) = "with schemaMeta" - fun(quote {
implicit val teSchemaMeta = testEntitySchemaMeta
query[TestEntity].insertValue(lift(e))
})

def `onConflict with querySchema`(fun: Quoted[Insert[TestEntity]] => Unit) =
"with querySchema" - fun(quote(testEntityQuerySchema.insertValue(lift(e))))

def `onConflict with all`(fun: Quoted[Insert[TestEntity]] => Unit) = {
`onConflict with query`(fun)
`onConflict with schemaMeta`(fun)
`onConflict with querySchema`(fun)
}

def del = quote(query[TestEntity].delete)

def `no target - ignore` = quote {
def `no target - ignore`(ins: Quoted[Insert[TestEntity]]) = quote {
ins.onConflictIgnore
}
def `cols target - ignore` = quote {
def `cols target - ignore`(ins: Quoted[Insert[TestEntity]]) = quote {
ins.onConflictIgnore(_.i)
}
def `no target - update` = quote {
def `no target - update`(ins: Quoted[Insert[TestEntity]]) = quote {
ins.onConflictUpdate((t, e) => t.l -> (t.l + e.l) / 2, _.s -> _.s)
}
def `cols target - update` = quote {
def `cols target - update`(ins: Quoted[Insert[TestEntity]]) = quote {
ins.onConflictUpdate(_.i, _.s)((t, e) => t.l -> (t.l + e.l) / 2, _.s -> _.s)
}
def insBatch = quote(liftQuery(List(e, TestEntity("s2", 1, 2L, Some(1), true))))
Expand Down
Expand Up @@ -44,22 +44,22 @@ class PostgresDialectSpec extends OnConflictSpec {
s"PREPARE p${id + 2} AS INSERT INTO tb (x1,x2,x3) VALUES ($$1,$$2,$$3)"
}

"OnConflict" - {
"OnConflict" - `onConflict with all` { i =>
"no target - ignore" in {
ctx.run(`no target - ignore`).string mustEqual
ctx.run(`no target - ignore`(i)).string mustEqual
"INSERT INTO TestEntity AS t (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON CONFLICT DO NOTHING"
}
"cols target - ignore" in {
ctx.run(`cols target - ignore`).string mustEqual
ctx.run(`cols target - ignore`(i)).string mustEqual
"INSERT INTO TestEntity (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON CONFLICT (i) DO NOTHING"
}
"no target - update" in {
intercept[IllegalStateException] {
ctx.run(`no target - update`.dynamic)
ctx.run(`no target - update`(i).dynamic)
}
}
"cols target - update" in {
ctx.run(`cols target - update`).string mustEqual
ctx.run(`cols target - update`(i)).string mustEqual
"INSERT INTO TestEntity AS t (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON CONFLICT (i,s) DO UPDATE SET l = ((t.l + EXCLUDED.l) / 2), s = EXCLUDED.s"
}
}
Expand Down
Expand Up @@ -35,22 +35,22 @@ class SqliteDialectSpec extends OnConflictSpec {
"SELECT 1 AS _1, 0 AS _2 FROM TestEntity t"
}

"OnConflict" - {
"OnConflict" - `onConflict with all` { i =>
"no target - ignore" in {
ctx.run(`no target - ignore`).string mustEqual
ctx.run(`no target - ignore`(i)).string mustEqual
"INSERT INTO TestEntity AS t (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON CONFLICT DO NOTHING"
}
"cols target - ignore" in {
ctx.run(`cols target - ignore`).string mustEqual
ctx.run(`cols target - ignore`(i)).string mustEqual
"INSERT INTO TestEntity (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON CONFLICT (i) DO NOTHING"
}
"no target - update" in {
intercept[IllegalStateException] {
ctx.run(`no target - update`.dynamic)
ctx.run(`no target - update`(i).dynamic)
}
}
"cols target - update" in {
ctx.run(`cols target - update`).string mustEqual
ctx.run(`cols target - update`(i)).string mustEqual
"INSERT INTO TestEntity AS t (s,i,l,o,b) VALUES (?, ?, ?, ?, ?) ON CONFLICT (i,s) DO UPDATE SET l = ((t.l + EXCLUDED.l) / 2), s = EXCLUDED.s"
}
}
Expand Down