Skip to content

Commit

Permalink
Merge branch 'master' into infrastructure-helper-cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
sviezypan authored May 31, 2022
2 parents eb38c2a + b2dc5dd commit f618284
Show file tree
Hide file tree
Showing 6 changed files with 97 additions and 96 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ Connection pool | :white_check_mark:

Feature | PostgreSQL | SQL Server | Oracle | MySQL
:------------ | :-------------| :-------------|:-------------------| :-------------
Render Read | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Render Read | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: | :heavy_check_mark: |
Render Delete | :heavy_check_mark: | :heavy_check_mark: | :white_check_mark: | :white_check_mark: |
Render Update | :heavy_check_mark: | | :white_check_mark: | :white_check_mark: |
Render Insert | :heavy_check_mark: | | |
Render Update | :heavy_check_mark: | | :white_check_mark: | :white_check_mark: |
Render Insert | :heavy_check_mark: | | | :white_check_mark: |
Functions | :heavy_check_mark: | :white_check_mark: | :white_check_mark: | :white_check_mark: |
Types | :white_check_mark: | | | :white_check_mark: |
Operators | | | |
Types | :white_check_mark: | | | :white_check_mark: |
Operators | | | | |

## What is ZIO SQL?
ZIO SQL lets you write type-safe, type-inferred, and composable SQL queries in ordinary Scala, helping you prevent persistence bugs before they happen, and leverage your IDE to make writing SQL productive, safe, and fun.
Expand Down
4 changes: 2 additions & 2 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ lazy val jdbc = project
libraryDependencies ++= Seq(
"dev.zio" %% "zio-test" % zioVersion % Test,
"dev.zio" %% "zio-test-sbt" % zioVersion % Test,
"org.postgresql" % "postgresql" % "42.3.5" % Test,
"org.postgresql" % "postgresql" % "42.3.6" % Test,
"com.dimafeng" %% "testcontainers-scala-postgresql" % testcontainersScalaVersion % Test
)
)
Expand Down Expand Up @@ -178,7 +178,7 @@ lazy val postgres = project
"org.testcontainers" % "database-commons" % testcontainersVersion % Test,
"org.testcontainers" % "postgresql" % testcontainersVersion % Test,
"org.testcontainers" % "jdbc" % testcontainersVersion % Test,
"org.postgresql" % "postgresql" % "42.3.5" % Compile,
"org.postgresql" % "postgresql" % "42.3.6" % Compile,
"com.dimafeng" %% "testcontainers-scala-postgresql" % testcontainersScalaVersion % Test
)
)
Expand Down
1 change: 1 addition & 0 deletions mysql/src/main/scala/zio/sql/mysql/MysqlSqlModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ trait MysqlSqlModule extends Sql { self =>
val MakeTime = FunctionDef[(Int, Int, Double), LocalTime](FunctionName("maketime"))
val Now = FunctionDef[Any, ZonedDateTime](FunctionName("now"))
val Pi = Expr.FunctionCall0[Double](FunctionDef[Any, Double](FunctionName("pi")))
val Soundex = FunctionDef[String, String](FunctionName("soundex"))
val Rand = FunctionDef[Int, Double](FunctionName("rand"))
val RPad = FunctionDef[(String, Int, String), String](FunctionName("rpad"))
val Uuid = Expr.FunctionCall0[UUID](FunctionDef[Any, UUID](FunctionName("uuid")))
Expand Down
32 changes: 32 additions & 0 deletions mysql/src/test/scala/zio/sql/mysql/FunctionDefSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,38 @@ object FunctionDefSpec extends MysqlRunnableSpec with ShopSchema {

assertZIO(testResult.runHead.some)(equalTo(expected))
},
test("soundex outputs should not match for non-similar-sounding strings") {
val queryForRobert = select(Soundex("Robert"))
val queryForTam = select(Soundex("Tam"))

val resultForRobert = execute(queryForRobert)
val resultForTam = execute(queryForTam)

for {
robertResult <- resultForRobert.runCollect
tamResult <- resultForTam.runCollect
} yield assert(robertResult.head.equals(tamResult.head))(equalTo(false))
},
test("soundex outputs should match for equivalent strings") {
val queryForRobert = select(Soundex("Robert"))
val queryForRupert = select(Soundex("Rupert"))

val resultForRobert = execute(queryForRobert)
val resultForRupert = execute(queryForRupert)

for {
robertResult <- resultForRobert.runCollect
rupertResult <- resultForRupert.runCollect
} yield assert(robertResult.head.equals(rupertResult.head))(equalTo(true))
},
test("soundex") {
val query = select(Soundex("Robert"))
val expected = "R163"

val testResult = execute(query)

assertZIO(testResult.runHead.some)(equalTo(expected))
},
test("current_date") {
val query = select(CurrentDate)

Expand Down
90 changes: 45 additions & 45 deletions postgres/src/main/scala/zio/sql/postgresql/PostgresSqlModule.scala
Original file line number Diff line number Diff line change
Expand Up @@ -246,47 +246,36 @@ trait PostgresSqlModule extends Sql { self =>
object PostgresFunctionDef {
import PostgresSpecific._

val SplitPart = FunctionDef[(String, String, Int), String](FunctionName("split_part"))
val IsFinite = FunctionDef[Instant, Boolean](FunctionName("isfinite"))
val TimeOfDay = FunctionDef[Any, String](FunctionName("timeofday"))
val CurrentTime = Expr.ParenlessFunctionCall0[OffsetTime](FunctionName("current_time"))
val BitLength = FunctionDef[String, Int](FunctionName("bit_length"))
val CBRT = FunctionDef[Double, Double](FunctionName("cbrt"))
val CharLength = FunctionDef[String, Int](FunctionName("character_length"))
val Localtime = Expr.ParenlessFunctionCall0[LocalTime](FunctionName("localtime"))
val LocaltimeWithPrecision = FunctionDef[Int, LocalTime](FunctionName("localtime"))
val Localtimestamp = Expr.ParenlessFunctionCall0[Instant](FunctionName("localtimestamp"))
val LocaltimestampWithPrecision = FunctionDef[Int, Instant](FunctionName("localtimestamp"))
val Md5 = FunctionDef[String, String](FunctionName("md5"))
val ParseIdent = FunctionDef[String, String](FunctionName("parse_ident"))
val Chr = FunctionDef[Int, String](FunctionName("chr"))
val CurrentDate = Expr.ParenlessFunctionCall0[LocalDate](FunctionName("current_date"))
val Initcap = FunctionDef[String, String](FunctionName("initcap"))
val Repeat = FunctionDef[(String, Int), String](FunctionName("repeat"))
val Reverse = FunctionDef[String, String](FunctionName("reverse"))
val TrimScale = FunctionDef[Double, Double](FunctionName("trim_scale"))
val Hex = FunctionDef[Int, String](FunctionName("to_hex"))
val Left = FunctionDef[(String, Int), String](FunctionName("left"))
val Length = FunctionDef[String, Int](FunctionName("length"))
val MinScale = FunctionDef[Double, Int](FunctionName("min_scale"))
val Radians = FunctionDef[Double, Double](FunctionName("radians"))
val Right = FunctionDef[(String, Int), String](FunctionName("right"))
val StartsWith = FunctionDef[(String, String), Boolean](FunctionName("starts_with"))
val Translate = FunctionDef[(String, String, String), String](FunctionName("translate"))
val Trunc = FunctionDef[Double, Double](FunctionName("trunc"))
val Sind = FunctionDef[Double, Double](FunctionName("sind"))
val GCD = FunctionDef[(Double, Double), Double](FunctionName("gcd"))
val LCM = FunctionDef[(Double, Double), Double](FunctionName("lcm"))
val CBRT = FunctionDef[Double, Double](FunctionName("cbrt"))
val CurrentTime = Expr.ParenlessFunctionCall0[OffsetTime](FunctionName("current_time"))
val Decode = FunctionDef[(String, String), Chunk[Byte]](FunctionName("decode"))
val Degrees = FunctionDef[Double, Double](FunctionName("degrees"))
val Div = FunctionDef[(Double, Double), Double](FunctionName("div"))
val Encode = FunctionDef[(Chunk[Byte], String), String](FunctionName("encode"))
val Factorial = FunctionDef[Int, Int](FunctionName("factorial"))
val Random = FunctionDef[Any, Double](FunctionName("random"))
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"))
val GCD = FunctionDef[(Double, Double), Double](FunctionName("gcd"))
val GenRandomUuid = Expr.FunctionCall0[UUID](FunctionDef[Any, UUID](FunctionName("gen_random_uuid")))
val Hex = FunctionDef[Int, String](FunctionName("to_hex"))
val Initcap = FunctionDef[String, String](FunctionName("initcap"))
val IsFinite = FunctionDef[Instant, Boolean](FunctionName("isfinite"))
val LCM = FunctionDef[(Double, Double), Double](FunctionName("lcm"))
val Left = FunctionDef[(String, Int), String](FunctionName("left"))
val Length = FunctionDef[String, Int](FunctionName("length"))
val Localtime = Expr.ParenlessFunctionCall0[LocalTime](FunctionName("localtime"))
val Localtimestamp = Expr.ParenlessFunctionCall0[Instant](FunctionName("localtimestamp"))
val LocaltimestampWithPrecision = FunctionDef[Int, Instant](FunctionName("localtimestamp"))
val LocaltimeWithPrecision = FunctionDef[Int, LocalTime](FunctionName("localtime"))
val LPad = FunctionDef[(String, Int, String), String](FunctionName("lpad"))
val RPad = FunctionDef[(String, Int, String), String](FunctionName("rpad"))
val ToTimestamp = FunctionDef[Long, ZonedDateTime](FunctionName("to_timestamp"))
val PgClientEncoding = FunctionDef[Any, String](FunctionName("pg_client_encoding"))
val Now = FunctionDef[Any, ZonedDateTime](FunctionName("now"))
val StatementTimestamp = FunctionDef[Any, ZonedDateTime](FunctionName("statement_timestamp"))
val TransactionTimestamp = FunctionDef[Any, ZonedDateTime](FunctionName("transaction_timestamp"))
val MakeDate = FunctionDef[(Int, Int, Int), LocalDate](FunctionName("make_date"))
val MakeInterval = FunctionDef[Interval, Interval](FunctionName("make_interval"))
val MakeTime = FunctionDef[(Int, Int, Double), LocalTime](FunctionName("make_time"))
Expand All @@ -296,18 +285,29 @@ trait PostgresSqlModule extends Sql { self =>
)
val MakeTimestampz =
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"))
val SetSeed = FunctionDef[Double, Unit](FunctionName("setseed"))
val BitLength = FunctionDef[String, Int](FunctionName("bit_length"))
val Md5 = FunctionDef[String, String](FunctionName("md5"))
val MinScale = FunctionDef[Double, Int](FunctionName("min_scale"))
val Now = FunctionDef[Any, ZonedDateTime](FunctionName("now"))
val ParseIdent = FunctionDef[String, String](FunctionName("parse_ident"))
val PgClientEncoding = FunctionDef[Any, String](FunctionName("pg_client_encoding"))
val Pi = Expr.FunctionCall0[Double](FunctionDef[Any, Double](FunctionName("pi")))
val GenRandomUuid = Expr.FunctionCall0[UUID](FunctionDef[Any, UUID](FunctionName("gen_random_uuid")))
val Radians = FunctionDef[Double, Double](FunctionName("radians"))
val Random = FunctionDef[Any, Double](FunctionName("random"))
val Repeat = FunctionDef[(String, Int), String](FunctionName("repeat"))
val Reverse = FunctionDef[String, String](FunctionName("reverse"))
val Right = FunctionDef[(String, Int), String](FunctionName("right"))
val RPad = FunctionDef[(String, Int, String), String](FunctionName("rpad"))
val SetSeed = FunctionDef[Double, Unit](FunctionName("setseed"))
val Sind = FunctionDef[Double, Double](FunctionName("sind"))
val SplitPart = FunctionDef[(String, String, Int), String](FunctionName("split_part"))
val StartsWith = FunctionDef[(String, String), Boolean](FunctionName("starts_with"))
val StatementTimestamp = FunctionDef[Any, ZonedDateTime](FunctionName("statement_timestamp"))
val TimeOfDay = FunctionDef[Any, String](FunctionName("timeofday"))
val ToTimestamp = FunctionDef[Long, ZonedDateTime](FunctionName("to_timestamp"))
val TransactionTimestamp = FunctionDef[Any, ZonedDateTime](FunctionName("transaction_timestamp"))
val Translate = FunctionDef[(String, String, String), String](FunctionName("translate"))
val TrimScale = FunctionDef[Double, Double](FunctionName("trim_scale"))
val Trunc = FunctionDef[Double, Double](FunctionName("trunc"))
}

}
56 changes: 12 additions & 44 deletions postgres/src/test/scala/zio/sql/postgresql/FunctionDefSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,9 @@ object FunctionDefSpec extends PostgresRunnableSpec with DbSchema {
import Expr._

// note: a plain number (3) would and should not compile
val query = select(ConcatWs4("+", "1", "2", "3")) from customers

val expected = Seq( // note: one for each row
"1+2+3",
"1+2+3",
"1+2+3",
"1+2+3",
"1+2+3"
)
val query = select(ConcatWs4("+", "1", "2", "3"))

val expected = Seq("1+2+3")

val testResult = execute(query)
collectAndCompare(expected, testResult)
Expand Down Expand Up @@ -124,15 +118,9 @@ object FunctionDefSpec extends PostgresRunnableSpec with DbSchema {
test("format0") {
import Expr._

val query = select(Format0("Person")) from customers
val query = select(Format0("Person"))

val expected = Seq(
"Person",
"Person",
"Person",
"Person",
"Person"
)
val expected = Seq("Person")

val testResult = execute(query)
collectAndCompare(expected, testResult)
Expand Down Expand Up @@ -356,11 +344,7 @@ object FunctionDefSpec extends PostgresRunnableSpec with DbSchema {

val testResult = execute(query)

val assertion = for {
r <- testResult.runCollect
} yield assert(r.head)(equalTo(expected))

assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))
assertZIO(testResult.runHead.some)(equalTo(expected))
},
suite("parseIdent")(
test("parseIdent removes quoting of individual identifiers") {
Expand All @@ -373,26 +357,18 @@ object FunctionDefSpec extends PostgresRunnableSpec with DbSchema {
string2 <- someString
} yield s""""${string1}".${string2}"""

val assertion = check(genTestString) { (testString) =>
check(genTestString) { (testString) =>
val query = select(ParseIdent(testString))
val testResult = execute(query)

for {
r <- testResult.runCollect
} yield assert(r.head)(not(containsString("'")) && not(containsString("\"")))

assertZIO(testResult.runHead.some)(not(containsString("'")) && not(containsString("\"")))
}
assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))
},
test("parseIdent fails with invalid identifier") {
val query = select(ParseIdent("\'\"SomeSchema\".someTable.\'"))
val testResult = execute(query)

val assertion = for {
r <- testResult.runCollect.exit
} yield assert(r)(fails(anything))

assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))
assertZIO(testResult.runCollect.exit)(fails(anything))
}
) @@ ignore,
test("sqrt") {
Expand All @@ -402,11 +378,7 @@ object FunctionDefSpec extends PostgresRunnableSpec with DbSchema {

val testResult = execute(query)

val assertion = for {
r <- testResult.runCollect
} yield assert(r.head)(equalTo(expected))

assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))
assertZIO(testResult.runHead.some)(equalTo(expected))
},
test("chr") {
val query = select(Chr(65))
Expand Down Expand Up @@ -876,16 +848,12 @@ object FunctionDefSpec extends PostgresRunnableSpec with DbSchema {
assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))
},
test("setseed") {
val query = select(SetSeed(0.12), Random(), Random()) from customers
val query = select(SetSeed(0.12), Random(), Random())

val randomTupleForSeed = (0.019967750719779076, 0.8378369929936333)
val testResult = execute(query).map { case (_, b, c) => (b, c) }

val assertion = for {
r <- testResult.runCollect
} yield assert(r.take(2))(equalTo(Chunk(randomTupleForSeed, randomTupleForSeed)))

assertion.mapErrorCause(cause => Cause.stackless(cause.untraced))
assertZIO(testResult.runHead.some)(equalTo(randomTupleForSeed))
},
test("Can concat strings with concat function") {

Expand Down

0 comments on commit f618284

Please sign in to comment.