From 6bd7f7a8d5a462f0b4abec728a9b5f14e80cf754 Mon Sep 17 00:00:00 2001
From: Massimo Siani
Date: Wed, 10 Jan 2024 16:26:43 +0100
Subject: [PATCH 1/3] Add merge completion case
---
.../src/main/scala/data/Completion.scala | 1 +
.../scala/net/message/CommandComplete.scala | 2 ++
.../shared/src/test/scala/CommandTest.scala | 19 +++++++++++++++++++
3 files changed, 22 insertions(+)
diff --git a/modules/core/shared/src/main/scala/data/Completion.scala b/modules/core/shared/src/main/scala/data/Completion.scala
index 70fdbf51..44e6f849 100644
--- a/modules/core/shared/src/main/scala/data/Completion.scala
+++ b/modules/core/shared/src/main/scala/data/Completion.scala
@@ -64,6 +64,7 @@ object Completion {
case object Grant extends Completion
case object Revoke extends Completion
case object AlterIndex extends Completion
+ case class Merge(count: Int) extends Completion
// more ...
/**
diff --git a/modules/core/shared/src/main/scala/net/message/CommandComplete.scala b/modules/core/shared/src/main/scala/net/message/CommandComplete.scala
index 7bdcaaad..d759399a 100644
--- a/modules/core/shared/src/main/scala/net/message/CommandComplete.scala
+++ b/modules/core/shared/src/main/scala/net/message/CommandComplete.scala
@@ -41,6 +41,7 @@ object CommandComplete {
val Update: Regex = """UPDATE (\d+)""".r
val Insert: Regex = """INSERT (\d+ \d+)""".r
val Copy: Regex = """COPY (\d+)""".r
+ val Merge: Regex = """MERGE (\d+)""".r
}
//TODO: maybe make lazy val
@@ -102,6 +103,7 @@ object CommandComplete {
case "GRANT" => apply(Completion.Grant)
case "REVOKE" => apply(Completion.Revoke)
case "ALTER INDEX" => apply(Completion.AlterIndex)
+ case Patterns.Merge(s) => apply(Completion.Merge(s.toInt))
// more .. fill in as we hit them
case s => apply(Completion.Unknown(s))
diff --git a/modules/tests/shared/src/test/scala/CommandTest.scala b/modules/tests/shared/src/test/scala/CommandTest.scala
index 96458e14..bfcd029d 100644
--- a/modules/tests/shared/src/test/scala/CommandTest.scala
+++ b/modules/tests/shared/src/test/scala/CommandTest.scala
@@ -94,6 +94,13 @@ class CommandTest extends SkunkTest {
WHERE id = $int4
""".command
+ val mergeCity: Command[Int] =
+ sql"""
+ MERGE INTO city
+ USING (VALUES ($int4)) t(city_id) ON t.city_id = city.id
+ WHEN MATCHED THEN DELETE
+ """.command
+
val createTable: Command[Void] =
sql"""
CREATE TABLE IF NOT EXISTS earth (
@@ -524,6 +531,18 @@ class CommandTest extends SkunkTest {
} yield "ok"
}
+ sessionTest("merge a record") { s =>
+ for {
+ c <- s.prepare(insertCity).flatMap(_.execute(Garin))
+ _ <- assert("completion", c == Completion.Insert(1))
+ c <- s.prepare(mergeCity).flatMap(_.execute(Garin.id))
+ _ <- assert("merge", c == Completion.Merge(1))
+ c <- s.prepare(selectCity).flatMap(_.option(Garin.id))
+ _ <- assert("read", c == None)
+ _ <- s.assertHealthy
+ } yield "ok"
+ }
+
sessionTest("pipe") { s =>
for {
_ <- s.execute(sql"delete from city where name like 'Pipe%'".command)
From b90205f1d74010f951f7a18e978e0a845c69f66e Mon Sep 17 00:00:00 2001
From: Massimo Siani
Date: Thu, 11 Jan 2024 23:50:23 +0100
Subject: [PATCH 2/3] avoid failure testing merge if not supported
---
bin/local | 2 +-
modules/tests/shared/src/test/scala/CommandTest.scala | 8 ++++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/bin/local b/bin/local
index d36bb84d..3e5f2800 100755
--- a/bin/local
+++ b/bin/local
@@ -28,4 +28,4 @@ esac
export SERVER_KEY=$(cat world/server.key)
export SERVER_CERT=$(cat world/server.crt)
-docker-compose $CMD $EXTRA_FLAGS
+docker compose $CMD $EXTRA_FLAGS
diff --git a/modules/tests/shared/src/test/scala/CommandTest.scala b/modules/tests/shared/src/test/scala/CommandTest.scala
index bfcd029d..79b8fce4 100644
--- a/modules/tests/shared/src/test/scala/CommandTest.scala
+++ b/modules/tests/shared/src/test/scala/CommandTest.scala
@@ -532,15 +532,19 @@ class CommandTest extends SkunkTest {
}
sessionTest("merge a record") { s =>
- for {
+ (for {
c <- s.prepare(insertCity).flatMap(_.execute(Garin))
_ <- assert("completion", c == Completion.Insert(1))
c <- s.prepare(mergeCity).flatMap(_.execute(Garin.id))
_ <- assert("merge", c == Completion.Merge(1))
c <- s.prepare(selectCity).flatMap(_.option(Garin.id))
_ <- assert("read", c == None)
+ _ <- s.execute(deleteCity)(Garin.id)
_ <- s.assertHealthy
- } yield "ok"
+ } yield "ok")
+ .recoverWith {
+ case SqlState.SyntaxError(ex) if ex.message.startsWith("""Syntax error at or near "MERGE"""") => s.execute(deleteCity)(Garin.id).as("ok")
+ }
}
sessionTest("pipe") { s =>
From 6d943be0f26e09d3ed3dc867f93680b5d77cbce3 Mon Sep 17 00:00:00 2001
From: Massimo Siani
Date: Fri, 12 Jan 2024 09:36:32 +0100
Subject: [PATCH 3/3] the merge test should only run if the pg version is 15 or
greater
---
.../shared/src/test/scala/CommandTest.scala | 28 +++++++++++--------
1 file changed, 16 insertions(+), 12 deletions(-)
diff --git a/modules/tests/shared/src/test/scala/CommandTest.scala b/modules/tests/shared/src/test/scala/CommandTest.scala
index 79b8fce4..3e7b5f47 100644
--- a/modules/tests/shared/src/test/scala/CommandTest.scala
+++ b/modules/tests/shared/src/test/scala/CommandTest.scala
@@ -532,18 +532,22 @@ class CommandTest extends SkunkTest {
}
sessionTest("merge a record") { s =>
- (for {
- c <- s.prepare(insertCity).flatMap(_.execute(Garin))
- _ <- assert("completion", c == Completion.Insert(1))
- c <- s.prepare(mergeCity).flatMap(_.execute(Garin.id))
- _ <- assert("merge", c == Completion.Merge(1))
- c <- s.prepare(selectCity).flatMap(_.option(Garin.id))
- _ <- assert("read", c == None)
- _ <- s.execute(deleteCity)(Garin.id)
- _ <- s.assertHealthy
- } yield "ok")
- .recoverWith {
- case SqlState.SyntaxError(ex) if ex.message.startsWith("""Syntax error at or near "MERGE"""") => s.execute(deleteCity)(Garin.id).as("ok")
+ s.unique(sql"SHOW server_version".query(skunk.codec.all.text))
+ .flatMap { version =>
+ val majorVersion = version.substring(0, 2).toInt
+ if (majorVersion >= 15) {
+ for {
+ c <- s.prepare(insertCity).flatMap(_.execute(Garin))
+ _ <- assert("completion", c == Completion.Insert(1))
+ c <- s.prepare(mergeCity).flatMap(_.execute(Garin.id))
+ _ <- assert("merge", c == Completion.Merge(1))
+ c <- s.prepare(selectCity).flatMap(_.option(Garin.id))
+ _ <- assert("read", c == None)
+ _ <- s.execute(deleteCity)(Garin.id)
+ _ <- s.assertHealthy
+ } yield "ok"
+ }
+ else IO.pure("skip")
}
}