diff --git a/build.sbt b/build.sbt index adc6a64e1..2bb621799 100644 --- a/build.sbt +++ b/build.sbt @@ -25,7 +25,7 @@ addCommandAlias("fmt", "fmtOnce;fmtOnce") addCommandAlias("check", "all scalafmtSbtCheck scalafmtCheck test:scalafmtCheck") val zioVersion = "1.0.5" -val testcontainersVersion = "1.15.2" +val testcontainersVersion = "1.15.3" val testcontainersScalaVersion = "0.39.3" lazy val startPostgres = taskKey[Unit]("Start up Postgres") @@ -160,7 +160,7 @@ lazy val mysql = project "org.testcontainers" % "database-commons" % testcontainersVersion % Test, "org.testcontainers" % "jdbc" % testcontainersVersion % Test, "org.testcontainers" % "mysql" % testcontainersVersion % Test, - "mysql" % "mysql-connector-java" % "8.0.23" % Test, + "mysql" % "mysql-connector-java" % "8.0.24" % Test, "com.dimafeng" %% "testcontainers-scala-mysql" % testcontainersScalaVersion % Test ) ) diff --git a/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala b/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala index 3d00da854..9cbdec184 100644 --- a/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala +++ b/postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala @@ -227,6 +227,12 @@ trait PostgresModule extends Jdbc { self => FunctionDef[Timestampz, Timestampz](FunctionName("make_timestamptz")) val Encode = FunctionDef[(Chunk[Byte], String), String](FunctionName("encode")) val Decode = FunctionDef[(String, String), Chunk[Byte]](FunctionName("decode")) + val Format0 = FunctionDef[String, String](FunctionName("format")) // TODO: varargs + val Format1 = FunctionDef[(String, Any), String](FunctionName("format")) + val Format2 = FunctionDef[(String, Any, Any), String](FunctionName("format")) + val Format3 = FunctionDef[(String, Any, Any, Any), String](FunctionName("format")) + val Format4 = FunctionDef[(String, Any, Any, Any, Any), String](FunctionName("format")) + val Format5 = FunctionDef[(String, Any, Any, Any, Any, Any), String](FunctionName("format")) } override def renderRead(read: self.Read[_]): String = { diff --git a/postgres/src/test/scala/zio/sql/postgresql/FunctionDefSpec.scala b/postgres/src/test/scala/zio/sql/postgresql/FunctionDefSpec.scala index e399fb3a5..fb900d8a3 100644 --- a/postgres/src/test/scala/zio/sql/postgresql/FunctionDefSpec.scala +++ b/postgres/src/test/scala/zio/sql/postgresql/FunctionDefSpec.scala @@ -151,7 +151,124 @@ object FunctionDefSpec extends PostgresRunnableSpec with ShopSchema { } yield assert(r.head)(equalTo(expected)) assertion.mapErrorCause(cause => Cause.stackless(cause.untraced)) - } + }, + suite("format function")( + testM("format0") { + import Expr._ + + val query = select(Format0("Person")) from customers + + val expected = Seq( + "Person", + "Person", + "Person", + "Person", + "Person" + ) + + val testResult = execute(query.to[String, String](identity)) + collectAndCompare(expected, testResult) + }, + testM("format1") { + import Expr._ + + val query = select(Format1("Person: %s", Customers.fName)) from customers + + val expected = Seq( + "Person: Ronald", + "Person: Terrence", + "Person: Mila", + "Person: Alana", + "Person: Jose" + ) + + val testResult = execute(query.to[String, String](identity)) + collectAndCompare(expected, testResult) + }, + testM("format2") { + import Expr._ + + val query = select(Format2("Person: %s %s", Customers.fName, Customers.lName)) from customers + + val expected = Seq( + "Person: Ronald Russell", + "Person: Terrence Noel", + "Person: Mila Paterso", + "Person: Alana Murray", + "Person: Jose Wiggins" + ) + + val testResult = execute(query.to[String, String](identity)) + collectAndCompare(expected, testResult) + }, + testM("format3") { + import Expr._ + + val query = select( + Format3("Person: %s %s with double quoted %I ", Customers.fName, Customers.lName, "identi fier") + ) from customers + + val expected = Seq( + s"""Person: Ronald Russell with double quoted "identi fier" """, + s"""Person: Terrence Noel with double quoted "identi fier" """, + s"""Person: Mila Paterso with double quoted "identi fier" """, + s"""Person: Alana Murray with double quoted "identi fier" """, + s"""Person: Jose Wiggins with double quoted "identi fier" """ + ) + + val testResult = execute(query.to[String, String](identity)) + collectAndCompare(expected, testResult) + }, + testM("format4") { + import Expr._ + + val query = select( + Format4( + "Person: %s %s with null-literal %L and non-null-literal %L ", + Customers.fName, + Customers.lName, + "FIXME: NULL", + "literal" + ) + ) from customers + + val expected = Seq( + s"""Person: Ronald Russell with null-literal 'FIXME: NULL' and non-null-literal 'literal' """, + s"""Person: Terrence Noel with null-literal 'FIXME: NULL' and non-null-literal 'literal' """, + s"""Person: Mila Paterso with null-literal 'FIXME: NULL' and non-null-literal 'literal' """, + s"""Person: Alana Murray with null-literal 'FIXME: NULL' and non-null-literal 'literal' """, + s"""Person: Jose Wiggins with null-literal 'FIXME: NULL' and non-null-literal 'literal' """ + ) + + val testResult = execute(query.to[String, String](identity)) + collectAndCompare(expected, testResult) + }, + testM("format5") { + import Expr._ + + val query = select( + Format5( + "Person: %s %s with more arguments than placeholders: %I %L ", + Customers.fName, + Customers.lName, + "identifier", + Reverse(Customers.fName), + "unused" + ) + ) from customers + + val expected = Seq( + s"""Person: Ronald Russell with more arguments than placeholders: identifier 'dlanoR' """, + s"""Person: Terrence Noel with more arguments than placeholders: identifier 'ecnerreT' """, + s"""Person: Mila Paterso with more arguments than placeholders: identifier 'aliM' """, + s"""Person: Alana Murray with more arguments than placeholders: identifier 'analA' """, + s"""Person: Jose Wiggins with more arguments than placeholders: identifier 'esoJ' """ + ) + + val testResult = execute(query.to[String, String](identity)) + collectAndCompare(expected, testResult) + } + ) ), testM("abs") { val query = select(Abs(-3.14159)) from customers @@ -358,7 +475,7 @@ object FunctionDefSpec extends PostgresRunnableSpec with ShopSchema { r <- testResult.runCollect } yield assert(r.head)( matchesRegex( - "[A-Za-z]{3}\\s[A-Za-z]{3}\\s[0-9]{2}\\s(2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9].[0-9]{6}\\s[0-9]{4}\\s[A-Za-z]{3}" + "[A-Za-z]{3}\\s[A-Za-z]{3}\\s[0-9]{2}\\s(2[0-3]|[01][0-9]):[0-5][0-9]:[0-5][0-9].[0-9]{6}\\s[0-9]{4}\\s[A-Za-z]{3,4}" ) ) assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))