diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3de36825..3f5ce4f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: java: [8, 11] - scala: [2.12.18, 2.13.12] + scala: [2.12.18, 2.13.12, 3.3.1] postgres: [11, 12, 13, 14] name: Test (Postgres ${{ matrix.postgres }} Scala ${{ matrix.scala }} Java ${{ matrix.java }}) runs-on: ubuntu-latest diff --git a/README.md b/README.md index 10c25464..eab4dc45 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ trait MyPostgresProfile extends ExPostgresProfile override val api = MyAPI object MyAPI extends ExtPostgresAPI with ArrayImplicits - with DateTimeImplicits + with Date2DateTimeImplicitsDuration with JsonImplicits with NetImplicits with LTreeImplicits @@ -91,7 +91,7 @@ class TestTable(tag: Tag) extends Table[Test](tag, Some("xxx"), "Test") { def props = column[Map[String,String]]("props_hstore") def tags = column[List[String]]("tags_arr") - def * = (id, during, location, text, props, tags) <> (Test.tupled, Test.unapply) + def * = (id, during, location, text, props, tags) <> ((Test.apply _).tupled, Test.unapply) } object tests extends TableQuery(new TestTable(_)) { diff --git a/addons/argonaut/src/test/scala/com/github/tminglei/slickpg/PgArgonautSupportSuite.scala b/addons/argonaut/src/test/scala/com/github/tminglei/slickpg/PgArgonautSupportSuite.scala index f6f1b850..21c351a4 100644 --- a/addons/argonaut/src/test/scala/com/github/tminglei/slickpg/PgArgonautSupportSuite.scala +++ b/addons/argonaut/src/test/scala/com/github/tminglei/slickpg/PgArgonautSupportSuite.scala @@ -1,17 +1,16 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import argonaut.Argonaut._ import argonaut._ import org.scalatest.funsuite.AnyFunSuite import slick.jdbc.{GetResult, PostgresProfile} -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import scala.concurrent.duration._ class PgArgonautSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends PostgresProfile with PgArgonautSupport @@ -24,7 +23,7 @@ class PgArgonautSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val strListTypeMapper: DriverJdbcType[List[JsonField]] = new SimpleArrayJdbcType[String]("text").to(_.toList) } } object MyPostgresProfile extends MyPostgresProfile @@ -40,7 +39,7 @@ class PgArgonautSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def json = column[Json]("json") - def * = (id, json) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -158,7 +157,7 @@ class PgArgonautSupportSuite extends AnyFunSuite with PostgresContainer { test("Argonaut json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean] = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) val b = JsonBean(34L, """ { "a":101, "b":"aaa", "c":[3,4,5,9] } """.parseOption.getOrElse(jNull)) diff --git a/addons/circe-json/src/test/scala/com/github/tminglei/slickpg/PgCirceJsonSupportSuite.scala b/addons/circe-json/src/test/scala/com/github/tminglei/slickpg/PgCirceJsonSupportSuite.scala index f843b54a..ead7ffa9 100644 --- a/addons/circe-json/src/test/scala/com/github/tminglei/slickpg/PgCirceJsonSupportSuite.scala +++ b/addons/circe-json/src/test/scala/com/github/tminglei/slickpg/PgCirceJsonSupportSuite.scala @@ -1,18 +1,17 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import cats.syntax.either._ import io.circe._ import io.circe.parser._ import org.scalatest.funsuite.AnyFunSuite import slick.jdbc.{GetResult, PostgresProfile} -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import scala.concurrent.duration._ class PgCirceJsonSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends PostgresProfile with PgCirceJsonSupport @@ -25,7 +24,7 @@ class PgCirceJsonSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val strListTypeMapper: DriverJdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) } } object MyPostgresProfile extends MyPostgresProfile @@ -40,7 +39,7 @@ class PgCirceJsonSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def json = column[Json]("json") - def * = (id, json) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -137,7 +136,7 @@ class PgCirceJsonSupportSuite extends AnyFunSuite with PostgresContainer { test("Circe json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean] = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) val b = JsonBean(34L, parse(""" { "a":101, "b":"aaa", "c":[3,4,5,9] } """).getOrElse(Json.Null)) diff --git a/addons/jawn/src/test/scala/com/github/tminglei/slickpg/PgJawnJsonSupportSuite.scala b/addons/jawn/src/test/scala/com/github/tminglei/slickpg/PgJawnJsonSupportSuite.scala index 74731262..68309139 100644 --- a/addons/jawn/src/test/scala/com/github/tminglei/slickpg/PgJawnJsonSupportSuite.scala +++ b/addons/jawn/src/test/scala/com/github/tminglei/slickpg/PgJawnJsonSupportSuite.scala @@ -1,18 +1,16 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import org.typelevel.jawn._ import org.typelevel.jawn.ast._ - import org.scalatest.funsuite.AnyFunSuite import slick.jdbc.{GetResult, PostgresProfile} -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import scala.concurrent.duration._ class PgJawnJsonSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends PostgresProfile with PgJawnJsonSupport @@ -25,8 +23,8 @@ class PgJawnJsonSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) - implicit val jsonArrayTypeMapper = + implicit val strListTypeMapper: DriverJdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val jsonArrayTypeMapper: DriverJdbcType[List[JValue]] = new AdvancedArrayJdbcType[JValue](pgjson, (s) => utils.SimpleArrayUtils.fromString[JValue](JParser.parseUnsafe(_))(s).orNull, (v) => utils.SimpleArrayUtils.mkString[JValue](_.toString())(v) @@ -47,7 +45,7 @@ class PgJawnJsonSupportSuite extends AnyFunSuite with PostgresContainer { def json = column[JValue]("json", O.Default(JParser.parseUnsafe(""" {"a":"v1","b":2} """))) def jsons = column[List[JValue]]("jsons") - def * = (id, json, jsons) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json, jsons) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -173,7 +171,7 @@ class PgJawnJsonSupportSuite extends AnyFunSuite with PostgresContainer { test("Json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean1] = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) val b = JsonBean1(34L, JParser.parseUnsafe(""" { "a":101, "b":"aaa", "c":[3,4,5,9] } """)) diff --git a/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala b/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala index d15c8277..d4dc0dbe 100644 --- a/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala +++ b/addons/joda-time/src/main/scala/com/github/tminglei/slickpg/PgDateSupportJoda.scala @@ -22,9 +22,6 @@ trait PgDateSupportJoda extends date.PgDateExtensions with utils.PgCommonJdbcTyp } } - /// alias - trait DateTimeImplicits extends JodaDateTimeImplicits - trait JodaDateTimeFormatters { val jodaDateFormatter = ISODateTimeFormat.date() val jodaTimeFormatter = DateTimeFormat.forPattern("HH:mm:ss.SSSSSS") diff --git a/addons/joda-time/src/test/scala/com/github/tminglei/slickpg/PgDateSupportJodaSuite.scala b/addons/joda-time/src/test/scala/com/github/tminglei/slickpg/PgDateSupportJodaSuite.scala index 98ac444f..ed2c6ccc 100644 --- a/addons/joda-time/src/test/scala/com/github/tminglei/slickpg/PgDateSupportJodaSuite.scala +++ b/addons/joda-time/src/test/scala/com/github/tminglei/slickpg/PgDateSupportJodaSuite.scala @@ -1,15 +1,14 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import org.joda.time._ import org.scalatest.funsuite.AnyFunSuite import slick.jdbc.{GetResult, PostgresProfile} -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} class PgDateSupportJodaSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends PostgresProfile with PgDateSupportJoda { @@ -19,7 +18,7 @@ class PgDateSupportJodaSuite extends AnyFunSuite with PostgresContainer { val plainAPI = new API with JodaDateTimePlainImplicits /// - trait API extends JdbcAPI with DateTimeImplicits + trait API extends JdbcAPI with JodaDateTimeImplicits } object MyPostgresProfile extends MyPostgresProfile @@ -47,7 +46,7 @@ class PgDateSupportJodaSuite extends AnyFunSuite with PostgresContainer { def interval = column[Period]("interval") def instant = column[Instant]("instant") - def * = (id, date, time, datetime, datetimetz, interval, instant) <> (DatetimeBean.tupled, DatetimeBean.unapply) + def * = (id, date, time, datetime, datetimetz, interval, instant) <> ((DatetimeBean.apply _).tupled, DatetimeBean.unapply) } val Datetimes = TableQuery[DatetimeTable] @@ -248,7 +247,7 @@ class PgDateSupportJodaSuite extends AnyFunSuite with PostgresContainer { test("Joda time Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getDateBean = GetResult(r => DatetimeBean( + implicit val getDateBean: GetResult[DatetimeBean] = GetResult(r => DatetimeBean( r.nextLong(), r.nextLocalDate(), r.nextLocalTime(), r.nextLocalDateTime(), r.nextZonedDateTime(), r.nextPeriod(), r.nextInstant())) val b1 = new DatetimeBean(107L, LocalDate.parse("2010-11-03"), LocalTime.parse("12:33:01.101357"), diff --git a/addons/json4s/src/test/scala/com/github/tminglei/slickpg/PgJson4sSupportSuite.scala b/addons/json4s/src/test/scala/com/github/tminglei/slickpg/PgJson4sSupportSuite.scala index a973638c..6e84946a 100644 --- a/addons/json4s/src/test/scala/com/github/tminglei/slickpg/PgJson4sSupportSuite.scala +++ b/addons/json4s/src/test/scala/com/github/tminglei/slickpg/PgJson4sSupportSuite.scala @@ -1,16 +1,15 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import org.json4s._ import org.scalatest.funsuite.AnyFunSuite import slick.jdbc.{GetResult, PostgresProfile} -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import scala.concurrent.duration._ class PgJson4sSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends PostgresProfile with PgJson4sSupport @@ -26,8 +25,8 @@ class PgJson4sSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) - implicit val json4sJsonArrayTypeMapper = + implicit val strListTypeMapper: DriverJdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val json4sJsonArrayTypeMapper: DriverJdbcType[List[JValue]] = new AdvancedArrayJdbcType[JValue](pgjson, (s) => utils.SimpleArrayUtils.fromString[JValue](jsonMethods.parse(_))(s).orNull, (v) => utils.SimpleArrayUtils.mkString[JValue](j=>jsonMethods.compact(jsonMethods.render(j)))(v) @@ -49,7 +48,7 @@ class PgJson4sSupportSuite extends AnyFunSuite with PostgresContainer { def json = column[JValue]("json") def jsons = column[List[JValue]]("jsons") - def * = (id, json, jsons) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json, jsons) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -175,7 +174,7 @@ class PgJson4sSupportSuite extends AnyFunSuite with PostgresContainer { test("Json4s Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean1] = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) val b = JsonBean1(34L, parse(""" { "a":101, "b":"aaa", "c":[3,4,5,9] } """)) diff --git a/addons/jts/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala b/addons/jts/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala index 78b64706..1d0af859 100644 --- a/addons/jts/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala +++ b/addons/jts/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala @@ -1,19 +1,16 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import scala.concurrent.duration._ -import scala.concurrent.{Await, ExecutionContext} - +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import slick.jdbc.GetResult - import com.vividsolutions.jts.geom.{Geometry, Point} import com.vividsolutions.jts.io.{WKBWriter, WKTReader, WKTWriter} import org.scalatest.funsuite.AnyFunSuite class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends ExPostgresProfile with PgPostGISSupport { @@ -41,7 +38,7 @@ class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { def geom = column[Geometry]("geom") def geog = column[Geography]("geog") - def * = (id, geom, geog) <> (GeometryBean.tupled, GeometryBean.unapply) + def * = (id, geom, geog) <> ((GeometryBean.apply _).tupled, GeometryBean.unapply) } val GeomTests = TableQuery[GeomTestTable] @@ -52,7 +49,7 @@ class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def point = column[Point]("point") - def * = (id, point) <> (PointBean.tupled, PointBean.unapply) + def * = (id, point) <> ((PointBean.apply _).tupled, PointBean.unapply) } val PointTests = TableQuery[PointTestTable] @@ -830,7 +827,7 @@ class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { test("PostGIS Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val GetPointBeanResult = GetResult(r => PointBean(r.nextLong(), r.nextGeometry[Point]())) + implicit val GetPointBeanResult: GetResult[PointBean] = GetResult(r => PointBean(r.nextLong(), r.nextGeometry[Point]())) val b = PointBean(77L, wktReader.read("POINT(4 5)").asInstanceOf[Point]) diff --git a/addons/jts_lt/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala b/addons/jts_lt/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala index 5975a41e..636af4e8 100644 --- a/addons/jts_lt/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala +++ b/addons/jts_lt/src/test/scala/com/github/tminglei/slickpg/PgPostGISSupportSuite.scala @@ -1,19 +1,16 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import scala.concurrent.duration._ -import scala.concurrent.{Await, ExecutionContext} - +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import slick.jdbc.GetResult - import org.locationtech.jts.geom.{Geometry, Point} import org.locationtech.jts.io.{WKBWriter, WKTReader, WKTWriter} import org.scalatest.funsuite.AnyFunSuite class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends ExPostgresProfile with PgPostGISSupport { @@ -41,7 +38,7 @@ class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { def geom = column[Geometry]("geom") def geog = column[Geography]("geog") - def * = (id, geom, geog) <> (GeometryBean.tupled, GeometryBean.unapply) + def * = (id, geom, geog) <> ((GeometryBean.apply _).tupled, GeometryBean.unapply) } val GeomTests = TableQuery[GeomTestTable] @@ -52,7 +49,7 @@ class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def point = column[Point]("point") - def * = (id, point) <> (PointBean.tupled, PointBean.unapply) + def * = (id, point) <> ((PointBean.apply _).tupled, PointBean.unapply) } val PointTests = TableQuery[PointTestTable] @@ -816,7 +813,7 @@ class PgPostGISSupportSuite extends AnyFunSuite with PostgresContainer { test("PostGIS (lt) Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val GetPointBeanResult = GetResult(r => PointBean(r.nextLong(), r.nextGeometry[Point]())) + implicit val GetPointBeanResult: GetResult[PointBean] = GetResult(r => PointBean(r.nextLong(), r.nextGeometry[Point]())) val b = PointBean(77L, wktReader.read("POINT(4 5)").asInstanceOf[Point]) diff --git a/addons/play-json/src/test/scala/com/github/tminglei/slickpg/PgPlayJsonSupportSuite.scala b/addons/play-json/src/test/scala/com/github/tminglei/slickpg/PgPlayJsonSupportSuite.scala index 30a5ce5e..64384ccb 100644 --- a/addons/play-json/src/test/scala/com/github/tminglei/slickpg/PgPlayJsonSupportSuite.scala +++ b/addons/play-json/src/test/scala/com/github/tminglei/slickpg/PgPlayJsonSupportSuite.scala @@ -1,24 +1,28 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import scala.concurrent.duration._ -import scala.concurrent.{Await, ExecutionContext} - +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import play.api.libs.json._ -import slick.jdbc.{GetResult, PostgresProfile} - +import slick.jdbc.{GetResult, JdbcType, PostgresProfile} import com.github.tminglei.slickpg.utils.JsonUtils import org.scalatest.funsuite.AnyFunSuite +import play.api.libs.functional.syntax.toFunctionalBuilderOps +import slick.ast.BaseTypedType class PgPlayJsonSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) case class JBean(name: String, count: Int) object JBean { - implicit val jbeanFmt = Json.format[JBean] - implicit val jbeanWrt = Json.writes[JBean] + // jbeanFmt should just be this, but there's a bug in play-json for scala 3 that causes it to throw a java.lang.ClassCastException -- and we're not testing that here +// implicit val jbeanFmt: OFormat[JBean] = Json.format[JBean] + implicit val jbeanFmt: OFormat[JBean] = ( + (__ \ implicitly[JsonConfiguration].naming("name")).format[String] and + (__ \ implicitly[JsonConfiguration].naming("count")).format[Int] + )(JBean.apply _, x => (x.name, x.count)) + implicit val jbeanWrt: OWrites[JBean] = Json.writes[JBean] } trait MyPostgresProfile extends PostgresProfile @@ -32,14 +36,14 @@ class PgPlayJsonSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) - implicit val beanJsonTypeMapper = MappedJdbcType.base[JBean, JsValue](Json.toJson(_), _.as[JBean]) - implicit val jsonArrayTypeMapper = + implicit val strListTypeMapper: DriverJdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val beanJsonTypeMapper: JdbcType[JBean] with BaseTypedType[JBean] = MappedJdbcType.base[JBean, JsValue](Json.toJson(_), _.as[JBean]) + implicit val jsonArrayTypeMapper: DriverJdbcType[List[JsValue]] = new AdvancedArrayJdbcType[JsValue](pgjson, (s) => utils.SimpleArrayUtils.fromString[JsValue](Json.parse(_))(s).orNull, (v) => utils.SimpleArrayUtils.mkString[JsValue](_.toString())(v) ).to(_.toList) - implicit val beanArrayTypeMapper = + implicit val beanArrayTypeMapper: DriverJdbcType[List[JBean]] = new AdvancedArrayJdbcType[JBean](pgjson, (s) => utils.SimpleArrayUtils.fromString[JBean](Json.parse(_).as[JBean])(s).orNull, (v) => utils.SimpleArrayUtils.mkString[JBean](b => Json.stringify(Json.toJson(b)))(v) @@ -62,7 +66,7 @@ class PgPlayJsonSupportSuite extends AnyFunSuite with PostgresContainer { def jbean = column[JBean]("jbean") def jbeans = column[List[JBean]]("jbeans") - def * = (id, json, jsons, jbean, jbeans) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json, jsons, jbean, jbeans) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -207,7 +211,7 @@ class PgPlayJsonSupportSuite extends AnyFunSuite with PostgresContainer { test("Json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean1] = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) val b = JsonBean1(34L, Json.parse(""" { "a":101, "b":"aaa", "c":[3,4,5,9] } """)) diff --git a/addons/spray-json/src/test/scala/com/github/tminglei/slickpg/PgSprayJsonSupportSuite.scala b/addons/spray-json/src/test/scala/com/github/tminglei/slickpg/PgSprayJsonSupportSuite.scala index 3f14af20..218ee466 100644 --- a/addons/spray-json/src/test/scala/com/github/tminglei/slickpg/PgSprayJsonSupportSuite.scala +++ b/addons/spray-json/src/test/scala/com/github/tminglei/slickpg/PgSprayJsonSupportSuite.scala @@ -1,20 +1,20 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import org.scalatest.funsuite.AnyFunSuite -import slick.jdbc.{GetResult, PostgresProfile} +import slick.ast.BaseTypedType +import slick.jdbc.{GetResult, JdbcType, PostgresProfile} import spray.json._ -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import scala.concurrent.duration._ class PgSprayJsonSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) case class JBean(name: String, count: Int) object MyJsonProtocol extends DefaultJsonProtocol { - implicit val jbeanFormat = jsonFormat2(JBean) + implicit val jbeanFormat: RootJsonFormat[JBean] = jsonFormat2(JBean) } trait MyPostgresProfile extends PostgresProfile @@ -29,8 +29,8 @@ class PgSprayJsonSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { import MyJsonProtocol._ - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) - implicit val beanJsonTypeMapper = MappedJdbcType.base[JBean, JsValue](_.toJson, _.convertTo[JBean]) + implicit val strListTypeMapper: DriverJdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val beanJsonTypeMapper: JdbcType[JBean] with BaseTypedType[JBean] = MappedJdbcType.base[JBean, JsValue](_.toJson, _.convertTo[JBean]) } } object MyPostgresProfile extends MyPostgresProfile @@ -47,7 +47,7 @@ class PgSprayJsonSupportSuite extends AnyFunSuite with PostgresContainer { def json = column[JsValue]("json") def jbean = column[JBean]("jbean") - def * = (id, json, jbean) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json, jbean) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -145,19 +145,19 @@ class PgSprayJsonSupportSuite extends AnyFunSuite with PostgresContainer { ), // || JsonTests.filter(_.id === 33L).map(_.json || """ {"d":"test"} """.parseJson).result.head.map( - r => assert(""" {"a": 101, "b": "aaa", "c": [3, 4, 5, 9], "d": "test"} """.replace(" ", "") === r.toString().replace(" ", "")) + r => assert(""" {"a": 101, "b": "aaa", "c": [3, 4, 5, 9], "d": "test"} """.replace(" ", "") === r.toString.replace(" ", "")) ), // - JsonTests.filter(_.id === 33L).map(_.json - "c".bind).result.head.map( - r => assert(""" {"a": 101, "b": "aaa"} """.replace(" ", "") === r.toString().replace(" ", "")) + r => assert(""" {"a": 101, "b": "aaa"} """.replace(" ", "") === r.toString.replace(" ", "")) ), // #- JsonTests.filter(_.id === 33L).map(_.json #- List("c")).result.head.map( - r => assert(""" {"a": 101, "b": "aaa"} """.replace(" ", "") === r.toString().replace(" ", "")) + r => assert(""" {"a": 101, "b": "aaa"} """.replace(" ", "") === r.toString.replace(" ", "")) ), // #- JsonTests.filter(_.id === 33L).map(_.json.set(List("c"), """ [1] """.parseJson.bind)).result.head.map( - r => assert(""" {"a": 101, "b": "aaa", "c": [1]} """.replace(" ", "") === r.toString().replace(" ", "")) + r => assert(""" {"a": 101, "b": "aaa", "c": [1]} """.replace(" ", "") === r.toString.replace(" ", "")) ) ) ).andFinally( @@ -172,7 +172,7 @@ class PgSprayJsonSupportSuite extends AnyFunSuite with PostgresContainer { test("Spray json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean1] = GetResult(r => JsonBean1(r.nextLong(), r.nextJson())) val b = JsonBean1(34L, """ { "a":101, "b":"aaa", "c":[3,4,5,9] } """.parseJson) diff --git a/addons/upickle-json/src/test/scala/com/github/tminglei/slickpg/PgUPickleJsonSupportSuite.scala b/addons/upickle-json/src/test/scala/com/github/tminglei/slickpg/PgUPickleJsonSupportSuite.scala index a1ae4126..e4ebaaf1 100644 --- a/addons/upickle-json/src/test/scala/com/github/tminglei/slickpg/PgUPickleJsonSupportSuite.scala +++ b/addons/upickle-json/src/test/scala/com/github/tminglei/slickpg/PgUPickleJsonSupportSuite.scala @@ -1,15 +1,14 @@ package com.github.tminglei.slickpg import java.util.concurrent.Executors - import org.scalatest.funsuite.AnyFunSuite import slick.jdbc.{GetResult, PostgresProfile} -import scala.concurrent.{Await, ExecutionContext} +import scala.concurrent.{Await, ExecutionContext, ExecutionContextExecutorService} import scala.concurrent.duration._ class PgUPickleJsonSupportSuite extends AnyFunSuite with PostgresContainer { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) trait MyPostgresProfile extends PostgresProfile with PgUPickleJsonSupport @@ -22,7 +21,7 @@ class PgUPickleJsonSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI with JsonImplicits { - implicit val strListTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val strListTypeMapper: DriverJdbcType[List[String]] = new SimpleArrayJdbcType[String]("text").to(_.toList) } } object MyPostgresProfile extends MyPostgresProfile @@ -37,7 +36,7 @@ class PgUPickleJsonSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def json = column[ujson.Value]("json") - def * = (id, json) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -134,7 +133,7 @@ class PgUPickleJsonSupportSuite extends AnyFunSuite with PostgresContainer { test("UPickle json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean] = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) val b = JsonBean(34L, ujson.read(""" { "a":101, "b":"aaa", "c":[3,4,5,9] } """)) diff --git a/build.sbt b/build.sbt index aeeb521e..2ff960fa 100644 --- a/build.sbt +++ b/build.sbt @@ -1,14 +1,15 @@ val scala212 = "2.12.18" val scala213 = "2.13.12" +val scala3 = "3.3.1" lazy val commonSettings = Seq( organizationName := "slick-pg", organization := "com.github.tminglei", name := "slick-pg", - version := "0.22.0-M4", + version := "0.22.0-M5", scalaVersion := scala213, - crossScalaVersions := Seq(scala212, scala213), + crossScalaVersions := Seq(scala212, scala213, scala3), scalacOptions ++= Seq("-deprecation", "-feature", "-language:implicitConversions", "-language:reflectiveCalls", @@ -64,7 +65,7 @@ lazy val commonSettings = Seq( def mainDependencies(scalaVersion: String) = { Seq ( "org.scala-lang.modules" %% "scala-parser-combinators" % "2.3.0", - "org.scala-lang" % "scala-reflect" % scalaVersion, + "dev.zio" %% "izumi-reflect" % "2.3.8", "com.typesafe.slick" %% "slick" % "3.5.0-M5", "org.postgresql" % "postgresql" % "42.7.1", "org.scala-lang.modules" %% "scala-collection-compat" % "2.11.0", @@ -72,7 +73,7 @@ def mainDependencies(scalaVersion: String) = { "org.scalatest" %% "scalatest" % "3.2.17" % "test", "com.dimafeng" %% "testcontainers-scala-scalatest" % "0.41.0" % "test", "com.dimafeng" %% "testcontainers-scala-postgresql" % "0.41.0" % "test" - ) + ) ++ (if (scalaVersion.startsWith("3")) Nil else Seq("org.scala-lang" % "scala-reflect" % scalaVersion)) } lazy val slickPgCore = (project in file("./core")) diff --git a/core/src/main/scala/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala b/core/src/main/scala-2/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala similarity index 68% rename from core/src/main/scala/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala rename to core/src/main/scala-2/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala index c4f71751..31869062 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala +++ b/core/src/main/scala-2/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala @@ -1,9 +1,8 @@ -package com.github.tminglei.slickpg -package composite +package com.github.tminglei.slickpg.composite import slick.jdbc.{JdbcTypesComponent, PostgresProfile} -trait Struct extends AnyRef +trait Struct extends Product trait PgCompositeExtensions extends JdbcTypesComponent { driver: PostgresProfile => //TODO not implemented by now diff --git a/core/src/main/scala/com/github/tminglei/slickpg/composite/README.md b/core/src/main/scala-2/com/github/tminglei/slickpg/composite/README.md similarity index 100% rename from core/src/main/scala/com/github/tminglei/slickpg/composite/README.md rename to core/src/main/scala-2/com/github/tminglei/slickpg/composite/README.md diff --git a/core/src/main/scala/com/github/tminglei/slickpg/utils/TypeConverters.scala b/core/src/main/scala-2/com/github/tminglei/slickpg/utils/TypeConverters.scala similarity index 100% rename from core/src/main/scala/com/github/tminglei/slickpg/utils/TypeConverters.scala rename to core/src/main/scala-2/com/github/tminglei/slickpg/utils/TypeConverters.scala diff --git a/core/src/main/scala-3/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala b/core/src/main/scala-3/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala new file mode 100644 index 00000000..04e52248 --- /dev/null +++ b/core/src/main/scala-3/com/github/tminglei/slickpg/composite/PgCompositeExtensions.scala @@ -0,0 +1,14 @@ +package com.github.tminglei.slickpg.composite + +import izumi.reflect.macrortti.LightTypeTag +import izumi.reflect.Tag +import slick.jdbc.{JdbcTypesComponent, PostgresProfile} +import scala.annotation.static +import scala.collection.concurrent.TrieMap +import scala.reflect.{classTag, ClassTag} + +trait Struct extends AnyRef + +trait PgCompositeExtensions extends JdbcTypesComponent { driver: PostgresProfile => + //TODO not implemented by now +} diff --git a/core/src/main/scala-3/com/github/tminglei/slickpg/composite/README.md b/core/src/main/scala-3/com/github/tminglei/slickpg/composite/README.md new file mode 100644 index 00000000..7dda284d --- /dev/null +++ b/core/src/main/scala-3/com/github/tminglei/slickpg/composite/README.md @@ -0,0 +1,4 @@ +Supported Composite type Oper/Functions +--------------------------------------- + +_ps: only type mapper supported currently_ diff --git a/core/src/main/scala-3/com/github/tminglei/slickpg/utils/TypeConverters.scala b/core/src/main/scala-3/com/github/tminglei/slickpg/utils/TypeConverters.scala new file mode 100644 index 00000000..7fb8f191 --- /dev/null +++ b/core/src/main/scala-3/com/github/tminglei/slickpg/utils/TypeConverters.scala @@ -0,0 +1,64 @@ +package com.github.tminglei.slickpg +package utils + +import izumi.reflect.{Tag => TTag} +import izumi.reflect.macrortti.LightTypeTag +import slick.util.Logging +import java.sql.{Date, Time, Timestamp} +import java.time.{LocalDate, LocalDateTime, LocalTime} +import java.util.UUID + +case class RegisteredTypeConverter[From, To](convert: From => To) + +object TypeConverters extends Logging { + case class ConvConfig(from: LightTypeTag, to: LightTypeTag, var conv: (_ => _)) + + private var convConfigList = List[ConvConfig]() + + // register basic converters + implicit val StringToInt: RegisteredTypeConverter[String, Int] = RegisteredTypeConverter[String, Int](_.toInt) + implicit val StringToLong: RegisteredTypeConverter[String, Long] = RegisteredTypeConverter(_.toLong) + implicit val StringToShort: RegisteredTypeConverter[String, Short] = RegisteredTypeConverter(_.toShort) + implicit val StringToFloat: RegisteredTypeConverter[String, Float] = RegisteredTypeConverter(_.toFloat) + implicit val StringToDouble: RegisteredTypeConverter[String, Double] = RegisteredTypeConverter(_.toDouble) + implicit val StringToBoolean: RegisteredTypeConverter[String, Boolean] = RegisteredTypeConverter(pgBoolAdjust(_).toBoolean) + implicit val StringToByte: RegisteredTypeConverter[String, Byte] = RegisteredTypeConverter(_.toByte) + implicit val StringToUUID: RegisteredTypeConverter[String, UUID] = RegisteredTypeConverter(UUID.fromString) + implicit val IntToString: RegisteredTypeConverter[Int, String] = RegisteredTypeConverter(_.toString) + implicit val LongToString: RegisteredTypeConverter[Long, String] = RegisteredTypeConverter(_.toString) + implicit val ShortToString: RegisteredTypeConverter[Short, String] = RegisteredTypeConverter(_.toString) + implicit val FloatToString: RegisteredTypeConverter[Float, String] = RegisteredTypeConverter(_.toString) + implicit val DoubleToString: RegisteredTypeConverter[Double, String] = RegisteredTypeConverter(_.toString) + implicit val BooleanToString: RegisteredTypeConverter[Boolean, String] = RegisteredTypeConverter(_.toString.take(1)) + implicit val ByteToString: RegisteredTypeConverter[Byte, String] = RegisteredTypeConverter(_.toString) + implicit val UUIDToString: RegisteredTypeConverter[UUID, String] = RegisteredTypeConverter(_.toString) + implicit val StringToString: RegisteredTypeConverter[String, String] = RegisteredTypeConverter(identity) + // register date/time converters + implicit val StringToDate: RegisteredTypeConverter[String, Date] = RegisteredTypeConverter(Date.valueOf) + implicit val StringToTime: RegisteredTypeConverter[String, Time] = RegisteredTypeConverter(Time.valueOf) + implicit val StringToTimestamp: RegisteredTypeConverter[String, Timestamp] = RegisteredTypeConverter(Timestamp.valueOf) + implicit val DateToString: RegisteredTypeConverter[Date, String] = RegisteredTypeConverter(_.toString) + implicit val TimeToString: RegisteredTypeConverter[Time, String] = RegisteredTypeConverter(_.toString) + implicit val TimestampToString: RegisteredTypeConverter[Timestamp, String] = RegisteredTypeConverter(_.toString) + + implicit val StringToLocalDate: RegisteredTypeConverter[String, LocalDate] = RegisteredTypeConverter(LocalDate.parse) + implicit val StringToLocalTime: RegisteredTypeConverter[String, LocalTime] = RegisteredTypeConverter(LocalTime.parse) + + implicit val StringToLocalDateTime: RegisteredTypeConverter[String, LocalDateTime] = + RegisteredTypeConverter(v => LocalDateTime.parse(v.replace(' ', 'T'))) + + implicit val LocalDateToString: RegisteredTypeConverter[LocalDate, String] = RegisteredTypeConverter(_.toString) + implicit val LocalTimeToString: RegisteredTypeConverter[LocalTime, String] = RegisteredTypeConverter(_.toString) + implicit val LocalDateTimeToString: RegisteredTypeConverter[LocalDateTime, String] = RegisteredTypeConverter(_.toString) + + + def converter[FROM, TO](implicit converter: RegisteredTypeConverter[FROM, TO]): (FROM => TO) = converter.convert + + /// + private def pgBoolAdjust(s: String): String = + Option(s).map(_.toLowerCase) match { + case Some("t") => "true" + case Some("f") => "false" + case _ => s + } +} diff --git a/core/src/main/scala/com/github/tminglei/slickpg/geom/PgPostGISExtensions.scala b/core/src/main/scala/com/github/tminglei/slickpg/geom/PgPostGISExtensions.scala index 2c04914a..f3d95e4e 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/geom/PgPostGISExtensions.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/geom/PgPostGISExtensions.scala @@ -53,12 +53,12 @@ trait PgPostGISExtensions extends JdbcTypesComponent { driver: PostgresProfile = case Some(p) => om.column(GeomLibrary.LineFromEncodedPolyline, encodedPolyline.toNode, LiteralNode(p)) case None => om.column(GeomLibrary.LineFromEncodedPolyline, encodedPolyline.toNode) } - def makeBox[G1 <: GEOMETRY, P1, G2 <: GEOMETRY, P2, R](lowLeftPoint: Rep[P1], upRightPoint: Rep[P2])( - implicit tm: JdbcType[GEOMETRY], om: OptionMapperDSL.arg[G1, P1]#arg[G2, P2]#to[GEOMETRY, R]) = { + def makeBox[G <: GEOMETRY, P1, P2, R](lowLeftPoint: Rep[P1], upRightPoint: Rep[P2])( + implicit tm: JdbcType[GEOMETRY], om: OptionMapperDSL.arg[G, P1]#arg[G, P1]#to[GEOMETRY, R]) = { om.column(GeomLibrary.MakeBox, lowLeftPoint.toNode, upRightPoint.toNode) } - def makeBox3d[G1 <: GEOMETRY, P1, G2 <: GEOMETRY, P2, R](lowLeftPoint: Rep[P1], upRightPoint: Rep[P2])( - implicit tm: JdbcType[GEOMETRY], om: OptionMapperDSL.arg[G1, P1]#arg[G2, P2]#to[GEOMETRY, R]) = { + def makeBox3d[G <: GEOMETRY, P1, P2, R](lowLeftPoint: Rep[P1], upRightPoint: Rep[P2])( + implicit tm: JdbcType[GEOMETRY], om: OptionMapperDSL.arg[G, P1]#arg[G, P2]#to[GEOMETRY, R]) = { om.column(GeomLibrary.MakeBox3D, lowLeftPoint.toNode, upRightPoint.toNode) } def makeEnvelope(xmin: Rep[Double], ymin: Rep[Double], xmax: Rep[Double], ymax: Rep[Double], srid: Option[Int] = None)( @@ -75,8 +75,8 @@ trait PgPostGISExtensions extends JdbcTypesComponent { driver: PostgresProfile = case (None, Some(m)) => om.column(GeomLibrary.MakePointM, x.toNode, y.toNode, LiteralNode(m)) case (None, None) => om.column(GeomLibrary.MakePoint, x.toNode, y.toNode) } - def makeLine[G1 <: GEOMETRY, P1, G2 <: GEOMETRY, P2, R](point1: Rep[P1], point2: Rep[P2])( - implicit tm: JdbcType[GEOMETRY], om: OptionMapperDSL.arg[G1, P1]#arg[G2, P2]#to[GEOMETRY, R]) = { + def makeLine[G <: GEOMETRY, P1, P2, R](point1: Rep[P1], point2: Rep[P2])( + implicit tm: JdbcType[GEOMETRY], om: OptionMapperDSL.arg[G, P1]#arg[G, P2]#to[GEOMETRY, R]) = { om.column(GeomLibrary.MakeLine, point1.toNode, point2.toNode) } def makePolygon[G <: GEOMETRY, P, R](linestring: Rep[P])( diff --git a/core/src/main/scala/com/github/tminglei/slickpg/lobj/LargeObjectStreamingDBIOAction.scala b/core/src/main/scala/com/github/tminglei/slickpg/lobj/LargeObjectStreamingDBIOAction.scala index 26d6e9dd..a921b259 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/lobj/LargeObjectStreamingDBIOAction.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/lobj/LargeObjectStreamingDBIOAction.scala @@ -14,7 +14,7 @@ import slick.util.DumpInfo * @param largeObjectId The oid of the LargeObject to stream. * @param bufferSize The chunk size in bytes. Default to 8KB. */ -case class LargeObjectStreamingDBIOAction(largeObjectId: Long, bufferSize: Int = 1024 * 8) +case class LargeObjectStreamingDBIOAction(largeObjectId: Long, bufferSize: Int = 1024 * 8)(implicit proof: JdbcBackend#StreamingContext <:< JdbcBackend#Context) extends SynchronousDatabaseAction[ Array[Byte], Streaming[Array[Byte]], @@ -78,8 +78,8 @@ case class LargeObjectStreamingDBIOAction(largeObjectId: Long, bufferSize: Int = */ override def emitStream(context: JdbcBackend#StreamingContext, limit: Long, state: StreamState): StreamState = { //open the stream iff no stream state exists - val (stream, previousBytesRead) = state == null match { - case true => (openObject(context), 1) + val (stream, previousBytesRead) = (state == null) match { + case true => (openObject(proof(context)), 1) case false => state } diff --git a/core/src/main/scala/com/github/tminglei/slickpg/str/PgStringExtensions.scala b/core/src/main/scala/com/github/tminglei/slickpg/str/PgStringExtensions.scala index a3e28cd5..77f1db0c 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/str/PgStringExtensions.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/str/PgStringExtensions.scala @@ -27,7 +27,7 @@ trait PgStringExtensions extends JdbcTypesComponent { driver: PostgresProfile => } class PgStringColumnExtensionMethods[P1](val c: Rep[P1]) extends ExtensionMethods[String, P1] { - protected implicit def b1Type = implicitly[TypedType[String]] + protected def b1Type = implicitly[TypedType[String]] def ilike[P2, R](e: Rep[P2])(implicit om: o#arg[String, P2]#to[Boolean, R]) = { om.column(StringLibrary.ILike, n, e.toNode) @@ -58,7 +58,7 @@ trait PgStringExtensions extends JdbcTypesComponent { driver: PostgresProfile => } class PgStringByteaColumnExtensionMethods[P1](val c: Rep[P1]) extends ExtensionMethods[Array[Byte], P1] { - protected implicit def b1Type = implicitly[TypedType[Array[Byte]]] + protected def b1Type = implicitly[TypedType[Array[Byte]]] def convert[R](srcEncoding: Rep[String], destEncoding: Rep[String])(implicit om: o#to[Array[Byte], R]) = { om.column(StringLibrary.Convert, n, srcEncoding.toNode, destEncoding.toNode) diff --git a/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala b/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala index f11c25bf..8928afbc 100644 --- a/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala +++ b/core/src/main/scala/com/github/tminglei/slickpg/utils/PlainSQLUtils.scala @@ -2,26 +2,23 @@ package com.github.tminglei.slickpg.utils import slick.util.Logging +import izumi.reflect.{Tag => TTag} import scala.reflect.ClassTag import slick.jdbc.{GetResult, PositionedResult, SetParameter, PositionedParameters} -import scala.reflect.runtime.{universe => u} - object PlainSQLUtils extends Logging { import SimpleArrayUtils._ private[slickpg] var nextArrayConverters = Map.empty[String, PositionedResult => Option[Seq[_]]] /** used to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport */ - def addNextArrayConverter[T](conv: PositionedResult => Option[Seq[T]])(implicit ttag: u.TypeTag[T]) = { - logger.info(s"\u001B[36m >>> adding next array converter for ${u.typeOf[T]} \u001B[0m") - nextArrayConverters.synchronized { - val convKey = u.typeOf[T].toString + def addNextArrayConverter[T](conv: PositionedResult => Option[Seq[T]])(implicit ttag: TTag[T]) = { + logger.info(s"\u001B[36m >>> adding next array converter for ${ttag.tag.repr} \u001B[0m") + val convKey = ttag.tag.repr val existed = nextArrayConverters.get(convKey) if (existed.isDefined) logger.warn( - s"\u001B[31m >>> DUPLICATED next array converter for ${u.typeOf[T]}!!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" + s"\u001B[31m >>> DUPLICATED next array converter for ${ttag.tag.repr}!!! \u001B[36m If it's expected, pls ignore it.\u001B[0m" ) nextArrayConverters += (convKey -> conv) - } } /// diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncCoreSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncCoreSuite.scala index ce8d3793..69b30e4e 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncCoreSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncCoreSuite.scala @@ -22,7 +22,7 @@ class PgAggFuncCoreSuite extends AnyFunSuite with PostgresContainer { def x = column[Double]("x") def y = column[Double]("y") - def * = (name, count, x, y) <> (Tab.tupled, Tab.unapply) + def * = (name, count, x, y) <> ((Tab.apply _).tupled, Tab.unapply) } val tabs = TableQuery(new Tabs(_)) diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncSupportSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncSupportSuite.scala index 50e80b33..4fa97db6 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncSupportSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgAggFuncSupportSuite.scala @@ -9,9 +9,9 @@ class PgAggFuncSupportSuite extends AnyFunSuite with PostgresContainer { import ExPostgresProfile.api._ val PgArrayJdbcTypes = new array.PgArrayJdbcTypes with ExPostgresProfile {} - implicit val simpleIntListTypeMapper = new PgArrayJdbcTypes.SimpleArrayJdbcType[Int]("int4").to(_.toList) - implicit val simpleStrListTypeMapper = new PgArrayJdbcTypes.SimpleArrayJdbcType[String]("text").to(_.toList) - implicit val simpleDoubleListTypeMapper = new PgArrayJdbcTypes.SimpleArrayJdbcType[Double]("float8").to(_.toList) + implicit val simpleIntListTypeMapper: PgArrayJdbcTypes.DriverJdbcType[List[Int]] = new PgArrayJdbcTypes.SimpleArrayJdbcType[Int]("int4").to(_.toList) + implicit val simpleStrListTypeMapper: PgArrayJdbcTypes.DriverJdbcType[List[String]] = new PgArrayJdbcTypes.SimpleArrayJdbcType[String]("text").to(_.toList) + implicit val simpleDoubleListTypeMapper: PgArrayJdbcTypes.DriverJdbcType[List[Double]] = new PgArrayJdbcTypes.SimpleArrayJdbcType[Double]("float8").to(_.toList) lazy val db = Database.forURL(url = container.jdbcUrl, driver = "org.postgresql.Driver") @@ -24,7 +24,7 @@ class PgAggFuncSupportSuite extends AnyFunSuite with PostgresContainer { def x = column[Double]("x") def y = column[Double]("y") - def * = (name, count, bool, x, y) <> (Tab.tupled, Tab.unapply) + def * = (name, count, bool, x, y) <> ((Tab.apply _).tupled, Tab.unapply) } val tabs = TableQuery(new Tabs(_)) diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgAutoIncSeqColumnSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgAutoIncSeqColumnSuite.scala index 8b26bd52..e50f2c8f 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgAutoIncSeqColumnSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgAutoIncSeqColumnSuite.scala @@ -16,7 +16,7 @@ class PgAutoIncSeqColumnSuite extends AnyFunSuite with PostgresContainer { def name = column[String]("name") - def * = (id, name) <> (User.tupled, User.unapply) + def * = (id, name) <> ((User.apply _).tupled, User.unapply) } val AutoIncSeqTests = TableQuery[AutoIncSeqTestTable] @@ -26,7 +26,7 @@ class PgAutoIncSeqColumnSuite extends AnyFunSuite with PostgresContainer { def name = column[String]("name") - def * = (id, name) <> (User.tupled, User.unapply) + def * = (id, name) <> ((User.apply _).tupled, User.unapply) } val AutoIncSeqNameTests = TableQuery[AutoIncSeqNameTestTable] @@ -36,7 +36,7 @@ class PgAutoIncSeqColumnSuite extends AnyFunSuite with PostgresContainer { def name = column[String]("name") - def * = (id, name) <> (User.tupled, User.unapply) + def * = (id, name) <> ((User.apply _).tupled, User.unapply) } val AutoIncSeqFnTests = TableQuery[AutoIncSeqFnTestTable] @@ -53,7 +53,7 @@ class PgAutoIncSeqColumnSuite extends AnyFunSuite with PostgresContainer { def name = column[String]("name") - def * = (id, name) <> (User.tupled, User.unapply) + def * = (id, name) <> ((User.apply _).tupled, User.unapply) } val AutoIncSeqNameWithFnTests = TableQuery[AutoIncSeqNameWithFnTestTable] diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgInheritsSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgInheritsSuite.scala index 1b1d6526..7eb1d7c4 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgInheritsSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgInheritsSuite.scala @@ -20,7 +20,7 @@ class PgInheritsSuite extends AnyFunSuite with PostgresContainer { case class Tab1(col1: String, col2: String, col3: String, col4: Int) class Tabs1(tag: Tag) extends BaseT[Tab1](tag, "test_tab1") { - def * = (col1, col2, col3, col4) <> (Tab1.tupled, Tab1.unapply) + def * = (col1, col2, col3, col4) <> ((Tab1.apply _).tupled, Tab1.unapply) } val tabs1 = TableQuery(new Tabs1(_)) @@ -31,7 +31,7 @@ class PgInheritsSuite extends AnyFunSuite with PostgresContainer { val inherited = tabs1.baseTableRow def col5 = column[Long]("col5") - def * = (col1, col2, col3, col4, col5) <> (Tab2.tupled, Tab2.unapply) + def * = (col1, col2, col3, col4, col5) <> ((Tab2.apply _).tupled, Tab2.unapply) } val tabs2 = TableQuery(new Tabs2(_)) diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgUpsertSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgUpsertSuite.scala index 02af4418..8abdc0a7 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgUpsertSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgUpsertSuite.scala @@ -28,7 +28,7 @@ class PgUpsertSuite extends AnyFunSuite with PostgresContainer { def col1 = column[String]("col1") def col2 = column[Int]("col2") - def * = (id, col1, col2) <> (Bean.tupled, Bean.unapply) + def * = (id, col1, col2) <> ((Bean.apply _).tupled, Bean.unapply) } val UpsertTests = TableQuery[UpsertTestTable] @@ -152,7 +152,7 @@ class PgUpsertSuite extends AnyFunSuite with PostgresContainer { def code = column[String]("code", O.PrimaryKey) def col2 = column[Int]("col2") - def * = (id.?, code, col2) <> (Bean1.tupled, Bean1.unapply) + def * = (id.?, code, col2) <> ((Bean1.apply _).tupled, Bean1.unapply) } val UpsertTests1 = TableQuery[UpsertTestTable1] @@ -162,7 +162,7 @@ class PgUpsertSuite extends AnyFunSuite with PostgresContainer { def col2 = column[Int]("col2") def pk = primaryKey("pk_a1", code) - def * = (id.?, code, col2) <> (Bean1.tupled, Bean1.unapply) + def * = (id.?, code, col2) <> ((Bean1.apply _).tupled, Bean1.unapply) } val UpsertTests11 = TableQuery[UpsertTestTable11] @@ -325,7 +325,7 @@ class PgUpsertSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc) def code = column[String]("code", O.PrimaryKey) - def * = (id.?, code) <> (Bean12.tupled, Bean12.unapply) + def * = (id.?, code) <> ((Bean12.apply _).tupled, Bean12.unapply) } val UpsertTests12 = TableQuery[UpsertTestTable12] @@ -412,7 +412,7 @@ class PgUpsertSuite extends AnyFunSuite with PostgresContainer { def start = column[Int]("start") def end = column[Int]("end") - def * = (id, start, end) <> (Bean2.tupled, Bean2.unapply) + def * = (id, start, end) <> ((Bean2.apply _).tupled, Bean2.unapply) } val UpsertTests2 = TableQuery[UpsertTestTable2] diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncCoreSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncCoreSuite.scala index b7f5220a..c5029591 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncCoreSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncCoreSuite.scala @@ -25,7 +25,7 @@ class PgWindowFuncCoreSuite extends AnyFunSuite with PostgresContainer { def col3 = column[String]("COL3") def col4 = column[Int]("COL4") - def * = (col1, col2, col3, col4) <> (Tab.tupled, Tab.unapply) + def * = (col1, col2, col3, col4) <> ((Tab.apply _).tupled, Tab.unapply) } val tabs = TableQuery[Tabs] diff --git a/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncSupportSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncSupportSuite.scala index f3947a81..41deec20 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncSupportSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/PgWindowFuncSupportSuite.scala @@ -21,7 +21,7 @@ class PgWindowFuncSupportSuite extends AnyFunSuite with PostgresContainer { def col3 = column[String]("COL3") def col4 = column[Int]("COL4") - def * = (col1, col2, col3, col4) <> (Tab.tupled, Tab.unapply) + def * = (col1, col2, col3, col4) <> ((Tab.apply _).tupled, Tab.unapply) } val tabs = TableQuery[Tabs] diff --git a/core/src/test/scala/com/github/tminglei/slickpg/package.scala b/core/src/test/scala/com/github/tminglei/slickpg/package.scala index 29199870..2a5963aa 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/package.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/package.scala @@ -1,8 +1,8 @@ package com.github.tminglei import java.util.concurrent.Executors -import scala.concurrent.ExecutionContext +import scala.concurrent.{ExecutionContext, ExecutionContextExecutorService} package object slickpg { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) } diff --git a/core/src/test/scala/com/github/tminglei/slickpg/str/PgStringSupportSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/str/PgStringSupportSuite.scala index 4fcdca71..fe2d3d42 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/str/PgStringSupportSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/str/PgStringSupportSuite.scala @@ -34,7 +34,7 @@ class PgStringSupportSuite extends AnyFunSuite with PostgresContainer { val str = column[String]("str") val strArr = column[Array[Byte]]("str_arr") - def * = (id, str, strArr) <> (StrBean.tupled, StrBean.unapply) + def * = (id, str, strArr) <> ((StrBean.apply _).tupled, StrBean.unapply) } val stringTestTable = TableQuery[StringTestTable] diff --git a/core/src/test/scala/com/github/tminglei/slickpg/trgm/PgTrgmSupportSuite.scala b/core/src/test/scala/com/github/tminglei/slickpg/trgm/PgTrgmSupportSuite.scala index f27d639f..e54d1189 100644 --- a/core/src/test/scala/com/github/tminglei/slickpg/trgm/PgTrgmSupportSuite.scala +++ b/core/src/test/scala/com/github/tminglei/slickpg/trgm/PgTrgmSupportSuite.scala @@ -30,7 +30,7 @@ class PgTrgmSupportSuite extends AnyFunSuite with PostgresContainer { val id = column[Long]("id") val str = column[String]("str") - def * = (id, str) <> (StrBean.tupled, StrBean.unapply) + def * = (id, str) <> ((StrBean.apply _).tupled, StrBean.unapply) } val trgmTestTable = TableQuery[StringTestTable] diff --git a/examples/codegen-customization/codegen/src/main/scala/demo/MyPostgresDriver.scala b/examples/codegen-customization/codegen/src/main/scala/demo/MyPostgresDriver.scala index 4d4e2c64..82493b33 100644 --- a/examples/codegen-customization/codegen/src/main/scala/demo/MyPostgresDriver.scala +++ b/examples/codegen-customization/codegen/src/main/scala/demo/MyPostgresDriver.scala @@ -16,7 +16,7 @@ trait MyPostgresDriver extends ExPostgresProfile ////// trait MyAPI extends ExtPostgresAPI with ArrayImplicits - with DateTimeImplicits + with Date2DateTimeImplicitsDuration with RangeImplicits with HStoreImplicits with SearchImplicits diff --git a/examples/play-slick-example/app/util/MyPostgresDriver.scala b/examples/play-slick-example/app/util/MyPostgresDriver.scala index c0dc8bb3..f9893229 100644 --- a/examples/play-slick-example/app/util/MyPostgresDriver.scala +++ b/examples/play-slick-example/app/util/MyPostgresDriver.scala @@ -15,7 +15,7 @@ trait MyPostgresDriver extends ExPostgresDriver override val pgjson = "jsonb" /// override val api = new ExtPostgresAPI with ArrayImplicits - with DateTimeImplicits + with Date2DateTimeImplicitsDuration with PlayJsonImplicits with NetImplicits with LTreeImplicits diff --git a/src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala b/src/main/scala-2/com/github/tminglei/slickpg/PgCompositeSupport.scala similarity index 95% rename from src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala rename to src/main/scala-2/com/github/tminglei/slickpg/PgCompositeSupport.scala index f7dfa5e0..2cc04268 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgCompositeSupport.scala +++ b/src/main/scala-2/com/github/tminglei/slickpg/PgCompositeSupport.scala @@ -11,39 +11,39 @@ trait PgCompositeSupport extends utils.PgCommonJdbcTypes with array.PgArrayJdbcT protected lazy val emptyMembersAsNull = true //--- - def createCompositeJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): GenericJdbcType[T] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) new GenericJdbcType[T](sqlTypeName, util.mkCompositeFromString[T], util.mkStringFromComposite[T]) } - def createCompositeArrayJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeArrayJdbcType[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): AdvancedArrayJdbcType[T] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) new AdvancedArrayJdbcType[T](sqlTypeName, util.mkCompositeSeqFromString[T], util.mkStringFromCompositeSeq[T]) } /// Plain SQL support - def nextComposite[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def nextComposite[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): Option[T] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) r.nextStringOption().map(util.mkCompositeFromString[T]) } - def nextCompositeArray[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def nextCompositeArray[T <: Struct](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): Option[Seq[T]] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) r.nextStringOption().map(util.mkCompositeSeqFromString[T]) } - def createCompositeSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): SetParameter[T] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkSetParameter[T](sqlTypeName, util.mkStringFromComposite[T]) } - def createCompositeOptionSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeOptionSetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): SetParameter[Option[T]] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkOptionSetParameter[T](sqlTypeName, util.mkStringFromComposite[T]) } - def createCompositeArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): SetParameter[Seq[T]] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkArraySetParameter[T](sqlTypeName, seqToStr = Some(util.mkStringFromCompositeSeq[T])) } - def createCompositeOptionArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]) = { + def createCompositeOptionArraySetParameter[T <: Struct](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader)(implicit ev: u.TypeTag[T], tag: ClassTag[T]): SetParameter[Option[Seq[T]]] = { val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) utils.PlainSQLUtils.mkArrayOptionSetParameter[T](sqlTypeName, seqToStr = Some(util.mkStringFromCompositeSeq[T])) } diff --git a/src/main/scala-3/com/github/tminglei/slickpg/PgCompositeSupport.scala b/src/main/scala-3/com/github/tminglei/slickpg/PgCompositeSupport.scala new file mode 100644 index 00000000..da1570cc --- /dev/null +++ b/src/main/scala-3/com/github/tminglei/slickpg/PgCompositeSupport.scala @@ -0,0 +1,179 @@ +package com.github.tminglei.slickpg + +import izumi.reflect.macrortti.LightTypeTag +import izumi.reflect.{Tag => TTag} + +import scala.reflect.{ClassTag, classTag} +import composite.Struct +import slick.jdbc.{PositionedResult, PostgresProfile} +import slick.jdbc.SetParameter + +import scala.annotation.unchecked.uncheckedVariance +import scala.deriving.* +import scala.compiletime.{error, erasedValue, summonInline, summonFrom} +import utils.PgTokenHelper._ +import utils.TypeConverters._ +import utils.RegisteredTypeConverter + +case class TokenConverter[T](level: Int, fromTokenAndLevel: Int => Token => T, toToken: T => Token) { + def fromToken(t: Token): T = fromTokenAndLevel(level)(t) + def withLevel(l: Int): TokenConverter[T] = copy(level = l) +} + + +trait PgCompositeSupport extends utils.PgCommonJdbcTypes with array.PgArrayJdbcTypes { driver: PostgresProfile => + + protected lazy val emptyMembersAsNull = true + + inline implicit def baseConverter[T](using fromString: RegisteredTypeConverter[String, T], toStringFn: RegisteredTypeConverter[T, String]): TokenConverter[T] = new TokenConverter[T](0, + level => token => if (token == Null) null.asInstanceOf[T] else fromString.convert(getString(token, level)), + value => if (value == null) Null else Chunk(toStringFn.convert(value))) + + //--- + inline def createCompositeJdbcType[T <: Struct: ClassTag](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader): GenericJdbcType[T] = { + lazy val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + new GenericJdbcType[T](sqlTypeName, util.mkCompositeFromString[T], util.mkStringFromComposite[T]) + } + + inline def createCompositeArrayJdbcType[T <: Struct: ClassTag](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader): AdvancedArrayJdbcType[T] = { + lazy val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + new AdvancedArrayJdbcType[T](sqlTypeName, util.mkCompositeSeqFromString[T], util.mkStringFromCompositeSeq[T]) + } + + /// Plain SQL support + inline def nextComposite[T <: Struct: ClassTag](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader): Option[T] = { + val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + r.nextStringOption().map(util.mkCompositeFromString[T]) + } + + inline def nextCompositeArray[T <: Struct: ClassTag](r: PositionedResult, cl: ClassLoader = getClass.getClassLoader): Option[Seq[T]] = { + val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + r.nextStringOption().map(util.mkCompositeSeqFromString[T]) + } + + inline def createCompositeSetParameter[T <: Struct: ClassTag](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader): SetParameter[T] = { + val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + utils.PlainSQLUtils.mkSetParameter[T](sqlTypeName, util.mkStringFromComposite[T]) + } + + inline def createCompositeOptionSetParameter[T <: Struct: ClassTag](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader): SetParameter[Option[T]] = { + val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + utils.PlainSQLUtils.mkOptionSetParameter[T](sqlTypeName, util.mkStringFromComposite[T]) + } + + inline def createCompositeArraySetParameter[T <: Struct: ClassTag](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader): SetParameter[Seq[T]] = { + val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + utils.PlainSQLUtils.mkArraySetParameter[T](sqlTypeName, seqToStr = Some(util.mkStringFromCompositeSeq[T])) + } + + inline def createCompositeOptionArraySetParameter[T <: Struct: ClassTag](sqlTypeName: String, cl: ClassLoader = getClass.getClassLoader): SetParameter[Option[Seq[T]]] = { + val util = new PgCompositeSupportUtils(cl, emptyMembersAsNull) + utils.PlainSQLUtils.mkArrayOptionSetParameter[T](sqlTypeName, seqToStr = Some(util.mkStringFromCompositeSeq[T])) + } +} + +class PgCompositeSupportUtils(cl: ClassLoader, emptyMembersAsNull: Boolean) { + import scala.deriving.* + import scala.compiletime.{error, erasedValue, summonInline} + + inline def mkCompositeFromString[T] = { + val c = deriveOrSummon[T](-1) + (input: String) => + val root = grouping(Tokenizer.tokenize(input)) + c.fromToken(root) + } + + inline def mkStringFromComposite[T] = { + val c = deriveOrSummon[T](-1) + (value: T) => createString(c.toToken(value)) + } + + inline def mkCompositeSeqFromString[T] = { + val c: TokenConverter[Seq[T]] = deriveOrSummon[Seq[T]](-1) + (input: String) => + val root = grouping(Tokenizer.tokenize(input)) + c.fromToken(root) + } + + inline def mkStringFromCompositeSeq[T] = { + val c: TokenConverter[Seq[T]] = deriveOrSummon[Seq[T]](-1) + (value: Seq[T]) => createString(c.toToken(value)) + } + + def seqConverter[T](delegate: TokenConverter[T]): TokenConverter[Seq[T]] = TokenConverter[Seq[T]](delegate.level - 1, + _ => token => if (token == Null) null else getChildren(token).map(delegate.fromToken), + { + case vList: Seq[Any] => { + val members = Open("{") +: vList.map(delegate.toToken) :+ Close("}") + GroupToken(members) + } + case null => Null + case value => throw new IllegalArgumentException("WRONG type value: " + value) + }) + + private def isNull(token: Token): Boolean = token match { + case g@GroupToken(_) if emptyMembersAsNull => getChildren(g).forall(isNull) + case Null => true + case _ => false + } + + def optConverter[T](delegate: TokenConverter[T]): TokenConverter[Option[T]] = new TokenConverter[Option[T]](delegate.level, + _ => token => if (isNull(token)) None else Some(delegate.fromToken(token)), + { + case Some(v: T) => delegate.toToken(v) + case None => Null + case value => throw new IllegalArgumentException("WRONG type value: " + value) + }) + + inline def summonInstances[Elems <: Tuple](i: Int): List[TokenConverter[?]] = { + inline erasedValue[Elems] match { + case _: (elem *: elems) => deriveOrSummon[elem](i + 1) :: summonInstances[elems](i) + case _: EmptyTuple => Nil + } + } + + inline def deriveOrSummon[Elem](i: Int): TokenConverter[Elem] = summonFrom { + case m: Mirror.Of[Elem & Struct] => + summonFrom { case ct: ClassTag[Elem & Struct] => derived[Elem & Struct](i).asInstanceOf[TokenConverter[Elem]] } + case _: (Elem <:< Option[Any]) => + inline erasedValue[Elem] match { + case _: Option[t] => + val elemConverter: TokenConverter[t] = deriveOrSummon[t](i) + optConverter(elemConverter).asInstanceOf[TokenConverter[Elem]] + } + case _: (Elem <:< Seq[Any]) => + inline erasedValue[Elem] match { + case _: Seq[t] => + val elemConverter: TokenConverter[t] = deriveOrSummon[t](i + 1) + seqConverter(elemConverter).asInstanceOf[TokenConverter[Elem]] + } + case _ => summonInline[TokenConverter[Elem]].withLevel(i) + } + + def convertProduct[T <: Struct: ClassTag](i: Int)(p: Mirror.ProductOf[T], elems: => List[TokenConverter[?]]): TokenConverter[T] = + new TokenConverter[T](i, _ => token => + if (token == Null) null.asInstanceOf[T] + else { + val args = + getChildren(token) + .zip(elems) + .map { case (token, converter) => converter.fromToken(token) } + + classTag.runtimeClass.getConstructors.head.newInstance(args:_*).asInstanceOf[T] + }, value => + if (value == null) Null + else { + val tokens = value.asInstanceOf[Product].productIterator.zip(elems).toSeq.map({ + case (v, converter) => converter.asInstanceOf[TokenConverter[Any]].toToken(v) + }) + val members = Open("(") +: tokens :+ Close(")") + GroupToken(members) + }) + + inline def derived[T <: Struct: ClassTag](i: Int)(using m: Mirror.Of[T]): TokenConverter[T] = { + lazy val elemInstances = summonInstances[m.MirroredElemTypes](i) + inline m match + case p: Mirror.ProductOf[T] => convertProduct[T](i)(p, elemInstances) + } + +} diff --git a/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala index 35f6b47c..04772df4 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgArraySupport.scala @@ -1,9 +1,9 @@ package com.github.tminglei.slickpg +import izumi.reflect.{Tag => TTag} import java.util.UUID import java.sql.{Date, Time, Timestamp} import slick.jdbc.{GetResult, JdbcType, PositionedResult, PostgresProfile, SetParameter} -import scala.reflect.runtime.{universe => u} import scala.reflect.classTag trait PgArraySupport extends array.PgArrayExtensions with array.PgArrayJdbcTypes { driver: PostgresProfile => @@ -63,9 +63,9 @@ trait PgArraySupport extends array.PgArrayExtensions with array.PgArrayJdbcTypes } implicit class PgArrayPositionedResult(r: PositionedResult) { - def nextArray[T]()(implicit tpe: u.TypeTag[T]): Seq[T] = nextArrayOption[T]().getOrElse(Nil) - def nextArrayOption[T]()(implicit ttag: u.TypeTag[T]): Option[Seq[T]] = { - nextArrayConverters.get(u.typeOf[T].toString).map(_.apply(r)) + def nextArray[T]()(implicit tpe: TTag[T]): Seq[T] = nextArrayOption[T]().getOrElse(Nil) + def nextArrayOption[T]()(implicit ttag: TTag[T]): Option[Seq[T]] = { + nextArrayConverters.get(ttag.tag.repr).map(_.apply(r)) .getOrElse(simpleNextArray[T](r)).asInstanceOf[Option[Seq[T]]] } } diff --git a/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala b/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala index 271a7965..a480fa8a 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgDate2Support.scala @@ -29,7 +29,6 @@ trait PgDate2Support extends date.PgDateExtensions with utils.PgCommonJdbcTypes } /// alias - trait DateTimeImplicits extends Date2DateTimeImplicitsDuration trait DateTimeImplicitsPeriod extends Date2DateTimeImplicitsPeriod trait Date2DateTimeImplicitsDuration extends Date2DateTimeImplicits[Duration] diff --git a/src/main/scala/com/github/tminglei/slickpg/PgDateSupport.scala b/src/main/scala/com/github/tminglei/slickpg/PgDateSupport.scala index e8d57e9e..2900a60d 100644 --- a/src/main/scala/com/github/tminglei/slickpg/PgDateSupport.scala +++ b/src/main/scala/com/github/tminglei/slickpg/PgDateSupport.scala @@ -8,9 +8,6 @@ import slick.jdbc.{JdbcType, PostgresProfile} trait PgDateSupport extends date.PgDateExtensions with utils.PgCommonJdbcTypes with date.PgDateJdbcTypes { driver: PostgresProfile => import driver.api._ - /// alias - trait DateTimeImplicits extends SimpleDateTimeImplicits - trait SimpleDateTimeImplicits { implicit val simpleIntervalTypeMapper: JdbcType[Interval] = new GenericJdbcType[Interval]("interval", Interval.apply, hasLiteralForm=false) implicit val simpleTimestampTZTypeMapper: JdbcType[Calendar] = new GenericDateJdbcType[Calendar]("timestamptz", java.sql.Types.TIMESTAMP_WITH_TIMEZONE) diff --git a/src/test/scala-2/com/github/tminglei/slickpg/ScalaVersionShim.scala b/src/test/scala-2/com/github/tminglei/slickpg/ScalaVersionShim.scala new file mode 100644 index 00000000..36c7f7e8 --- /dev/null +++ b/src/test/scala-2/com/github/tminglei/slickpg/ScalaVersionShim.scala @@ -0,0 +1,25 @@ +package com.github.tminglei.slickpg + +import com.github.tminglei.slickpg.PgCompositeSupportSuite.ts +import org.postgresql.util.HStoreConverter + +import java.time.LocalDateTime +import scala.jdk.CollectionConverters._ + +object ScalaVersionShim { + def mapToString(m: Map[String, String]): String = HStoreConverter.toString((m).asJava) + def stringToMap(s: String): Map[String, String] = (HStoreConverter.fromString(s) + .asInstanceOf[java.util.Map[String, String]]).asScala.toMap + + def registerTypeConverters(): Unit = { + + utils.TypeConverters.register(PgRangeSupportUtils.mkRangeFn(ts)) + utils.TypeConverters.register(PgRangeSupportUtils.toStringFn[LocalDateTime](_.toString)) + utils.TypeConverters.register(mapToString) + utils.TypeConverters.register(stringToMap) + } + + object maybeTypeConverters {} +} + +object TypeConverters {} diff --git a/src/test/scala-3/com/github/tminglei/slickpg/ScalaVersionShim.scala b/src/test/scala-3/com/github/tminglei/slickpg/ScalaVersionShim.scala new file mode 100644 index 00000000..9d2f16dd --- /dev/null +++ b/src/test/scala-3/com/github/tminglei/slickpg/ScalaVersionShim.scala @@ -0,0 +1,24 @@ +package com.github.tminglei.slickpg + +import com.github.tminglei.slickpg.utils.{RegisteredTypeConverter,TypeConverters} + +import org.postgresql.util.HStoreConverter + +import java.time.LocalDateTime +import scala.jdk.CollectionConverters._ + +object ScalaVersionShim { + def ts(str: String) = LocalDateTime.parse(str.replace(' ', 'T')) + def mapToString(m: Map[String, String]): String = HStoreConverter.toString((m).asJava) + def stringToMap(s: String): Map[String, String] = (HStoreConverter.fromString(s) + .asInstanceOf[java.util.Map[String, String]]).asScala.toMap + implicit val StringToRange: RegisteredTypeConverter[String, Range[LocalDateTime]] = + RegisteredTypeConverter(PgRangeSupportUtils.mkRangeFn(ts)) + implicit val RangeToString: RegisteredTypeConverter[Range[LocalDateTime], String] = + RegisteredTypeConverter(PgRangeSupportUtils.toStringFn[LocalDateTime](_.toString)) + implicit val MapToString: RegisteredTypeConverter[Map[String, String], String] = RegisteredTypeConverter(mapToString) + implicit val StringToMap: RegisteredTypeConverter[String, Map[String, String]] = RegisteredTypeConverter(stringToMap) + + def registerTypeConverters(): Unit = () + val maybeTypeConverters: RegisteredTypeConverter.type = RegisteredTypeConverter +} diff --git a/src/test/scala/com/github/tminglei/slickpg/MyPostgresProfile.scala b/src/test/scala/com/github/tminglei/slickpg/MyPostgresProfile.scala index aaa4ad6a..262ce7ee 100644 --- a/src/test/scala/com/github/tminglei/slickpg/MyPostgresProfile.scala +++ b/src/test/scala/com/github/tminglei/slickpg/MyPostgresProfile.scala @@ -17,7 +17,7 @@ trait MyPostgresProfile extends ExPostgresProfile trait MyAPI extends ExtPostgresAPI with ArrayImplicits with SimpleDateTimeImplicits - with DateTimeImplicits + with Date2DateTimeImplicitsDuration with SimpleJsonImplicits with NetImplicits with LTreeImplicits diff --git a/src/test/scala/com/github/tminglei/slickpg/PgArraySupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgArraySupportSuite.scala index 281beeab..3eab1890 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgArraySupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgArraySupportSuite.scala @@ -2,10 +2,11 @@ package com.github.tminglei.slickpg import java.sql.{Date, Time, Timestamp} import java.util.UUID - import org.scalatest.funsuite.AnyFunSuite -import slick.jdbc.GetResult +import slick.ast.BaseTypedType +import slick.jdbc.{GetResult, JdbcType, SetParameter} +import scala.collection.mutable import scala.collection.mutable.Buffer import scala.concurrent.Await import scala.concurrent.duration._ @@ -22,27 +23,27 @@ class PgArraySupportSuite extends AnyFunSuite with PostgresContainer { /// trait MyAPI extends ExtPostgresAPI with ArrayImplicits { - implicit val simpleOptStrListListMapper = new SimpleArrayJdbcType[String]("text") + implicit val simpleOptStrListListMapper: DriverJdbcType[List[Option[String]]] = new SimpleArrayJdbcType[String]("text") .mapTo[Option[String]](Option(_), _.orNull).to(_.toList) - implicit val simpleLongBufferTypeMapper = new SimpleArrayJdbcType[Long]("int8").to(_.toBuffer[Long], (v: Buffer[Long]) => v.toSeq) - implicit val simpleStrVectorTypeMapper = new SimpleArrayJdbcType[String]("text").to(_.toVector) - implicit val institutionListTypeWrapper = new SimpleArrayJdbcType[Long]("int8") + implicit val simpleLongBufferTypeMapper: DriverJdbcType[mutable.Buffer[Long]] = new SimpleArrayJdbcType[Long]("int8").to(_.toBuffer[Long], (v: Buffer[Long]) => v.toSeq) + implicit val simpleStrVectorTypeMapper: DriverJdbcType[Vector[String]] = new SimpleArrayJdbcType[String]("text").to(_.toVector) + implicit val institutionListTypeWrapper: DriverJdbcType[List[Institution]] = new SimpleArrayJdbcType[Long]("int8") .mapTo[Institution](new Institution(_), _.value).to(_.toList) - implicit val marketFinancialProductWrapper = new SimpleArrayJdbcType[String]("text") + implicit val marketFinancialProductWrapper: DriverJdbcType[List[MarketFinancialProduct]] = new SimpleArrayJdbcType[String]("text") .mapTo[MarketFinancialProduct](new MarketFinancialProduct(_), _.value).to(_.toList) /// - implicit val bigDecimalTypeWrapper = new SimpleArrayJdbcType[java.math.BigDecimal]("numeric") + implicit val bigDecimalTypeWrapper: DriverJdbcType[List[BigDecimal]] = new SimpleArrayJdbcType[java.math.BigDecimal]("numeric") .mapTo[scala.math.BigDecimal](javaBigDecimal => scala.math.BigDecimal(javaBigDecimal), scalaBigDecimal => scalaBigDecimal.bigDecimal).to(_.toList) - implicit val advancedStringListTypeMapper = new AdvancedArrayJdbcType[String]("text", - fromString(identity)(_).orNull, mkString(identity)) + implicit val advancedStringListTypeMapper: AdvancedArrayJdbcType[String] = new AdvancedArrayJdbcType[String]("text", + fromString(identity)(_).orNull, mkString(identity[String])) /// - implicit val longlongWitness = ElemWitness.AnyWitness.asInstanceOf[ElemWitness[List[Long]]] - implicit val simpleLongLongListTypeMapper = new SimpleArrayJdbcType[List[Long]]("int8[]") + implicit val longlongWitness: ElemWitness[List[Long]] = ElemWitness.AnyWitness.asInstanceOf[ElemWitness[List[Long]]] + implicit val simpleLongLongListTypeMapper: DriverJdbcType[List[List[Long]]] = new SimpleArrayJdbcType[List[Long]]("int8[]") .to(_.asInstanceOf[Seq[Array[Any]]].toList.map(_.toList.asInstanceOf[List[Long]])) - implicit val institutionTypeWrapper = MappedJdbcType.base[Institution, Long](_.value, Institution) - implicit val marketFinancialProductTypeWrapper = MappedJdbcType.base[MarketFinancialProduct, String](_.value, MarketFinancialProduct) + implicit val institutionTypeWrapper: JdbcType[Institution] with BaseTypedType[Institution] = MappedJdbcType.base[Institution, Long](_.value, Institution) + implicit val marketFinancialProductTypeWrapper: JdbcType[MarketFinancialProduct] with BaseTypedType[MarketFinancialProduct] = MappedJdbcType.base[MarketFinancialProduct, String](_.value, MarketFinancialProduct) } } object MyPostgresProfile1 extends MyPostgresProfile1 @@ -84,7 +85,7 @@ class PgArraySupportSuite extends AnyFunSuite with PostgresContainer { def mktFinancialProducts = column[Option[List[MarketFinancialProduct]]]("mktFinancialProducts") def * = (id, str, intArr, longArr, longlongArr, shortArr, strList, optStrList, strArr, uuidArr, - bigDecimalArr, institutions, mktFinancialProducts) <> (ArrayBean.tupled, ArrayBean.unapply) + bigDecimalArr, institutions, mktFinancialProducts) <> ((ArrayBean.apply _).tupled, ArrayBean.unapply) } val ArrayTests = TableQuery[ArrayTestTable] @@ -125,7 +126,7 @@ class PgArraySupportSuite extends AnyFunSuite with PostgresContainer { r => assert(List(testRec2) === r) ), // @> - ArrayTests.filter(_.strArr @> Vector("str3")).sortBy(_.id).to[List].result.map( + ArrayTests.filter(_.strArr @> (Vector("str3"): Rep[Vector[String]])).sortBy(_.id).to[List].result.map( r => assert(List(testRec1, testRec2, testRec3) === r) ), ArrayTests.filter(_.mktFinancialProducts @> List(MarketFinancialProduct("product1"))).sortBy(_.id).to[List].result.map( @@ -206,12 +207,12 @@ class PgArraySupportSuite extends AnyFunSuite with PostgresContainer { addNextArrayConverter((r) => r.nextArrayOption[Long]().map(_.map(Institution(_)))) } - implicit val getInstitutionArray = mkGetResult(_.nextArray[Institution]()) - implicit val getInstitutionArrayOption = mkGetResult(_.nextArrayOption[Institution]()) - implicit val setInstitutionArray = mkArraySetParameter[Institution]("int8", v => String.valueOf(v.value)) - implicit val setInstitutionArrayOption = mkArrayOptionSetParameter[Institution]("int8", v => String.valueOf(v.value)) + implicit val getInstitutionArray: GetResult[Seq[Institution]] = mkGetResult(_.nextArray[Institution]()) + implicit val getInstitutionArrayOption: GetResult[Option[Seq[Institution]]] = mkGetResult(_.nextArrayOption[Institution]()) + implicit val setInstitutionArray: SetParameter[Seq[Institution]] = mkArraySetParameter[Institution]("int8", v => String.valueOf(v.value)) + implicit val setInstitutionArrayOption: SetParameter[Option[Seq[Institution]]] = mkArrayOptionSetParameter[Institution]("int8", v => String.valueOf(v.value)) - implicit val getArrarBean1Result = GetResult { r => + implicit val getArrarBean1Result: GetResult[ArrayBean1] = GetResult { r => ArrayBean1(r.nextLong(), r.<<[Array[Byte]], r.<<[Seq[UUID]].toList, @@ -254,7 +255,7 @@ class PgArraySupportSuite extends AnyFunSuite with PostgresContainer { sqlu"insert into ArrayTest1 values(${b.id}, ${b.bytea}, ${b.uuidArr}, ${b.strArr}, ${b.longArr}, ${b.intArr}, ${b.shortArr}, ${b.floatArr}, ${b.doubleArr}, ${b.boolArr}, ${b.dateArr}, ${b.timeArr}, ${b.tsArr}, ${b.institutionArr})", sql"select * from ArrayTest1 where id = ${b.id}".as[ArrayBean1].head.map( f => { - b.bytea.zip(f.bytea).map(r => assert(r._1 === r._2)) + b.bytea.toSeq.zip(f.bytea.toSeq).map(r => assert(r._1 === r._2)) b.uuidArr.zip(f.uuidArr).map(r => assert(r._1 === r._2)) b.strArr.getOrElse(Nil).zip(f.strArr.getOrElse(Nil)).map(r => assert(r._1 === r._2)) b.longArr.zip(f.longArr).map(r => assert(r._1 === r._2)) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgCompositeSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgCompositeSupportSuite.scala index 966ddb2b..4db28a8b 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgCompositeSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgCompositeSupportSuite.scala @@ -1,19 +1,21 @@ package com.github.tminglei.slickpg -import java.time.LocalDateTime +import com.github.tminglei.slickpg.composite.Struct +import org.postgresql.util.HStoreConverter +import org.scalatest.funsuite.AnyFunSuite +import slick.jdbc.{GetResult, PositionedResult, PostgresProfile, SetParameter} +import com.github.tminglei.slickpg.utils.TypeConverters +import java.time.LocalDateTime import scala.concurrent.Await import scala.concurrent.duration._ import scala.jdk.CollectionConverters._ -import slick.jdbc.{GetResult, PositionedResult, PostgresProfile} - -import com.github.tminglei.slickpg.composite.Struct -import org.postgresql.util.HStoreConverter -import org.scalatest.funsuite.AnyFunSuite - object PgCompositeSupportSuite { + import TypeConverters._ + import ScalaVersionShim._ + import ScalaVersionShim.maybeTypeConverters._ def ts(str: String) = LocalDateTime.parse(str.replace(' ', 'T')) case class Composite1( @@ -62,25 +64,22 @@ object PgCompositeSupportSuite { /// trait API extends JdbcAPI with ArrayImplicits { - utils.TypeConverters.register(PgRangeSupportUtils.mkRangeFn(ts)) - utils.TypeConverters.register(PgRangeSupportUtils.toStringFn[LocalDateTime](_.toString)) - utils.TypeConverters.register(mapToString) - utils.TypeConverters.register(stringToMap) - - implicit val composite1TypeMapper = createCompositeJdbcType[Composite1]("composite1") - implicit val composite2TypeMapper = createCompositeJdbcType[Composite2]("composite2") - implicit val composite3TypeMapper = createCompositeJdbcType[Composite3]("composite3") - implicit val composite4TypeMapper = createCompositeJdbcType[Composite4]("composite4") - implicit val c1TypeMapper = createCompositeJdbcType[C1]("c1") - implicit val c2TypeMapper = createCompositeJdbcType[C2]("c2") - - implicit val composite1ArrayTypeMapper = createCompositeArrayJdbcType[Composite1]("composite1").to(_.toList) - implicit val composite2ArrayTypeMapper = createCompositeArrayJdbcType[Composite2]("composite2").to(_.toList) - implicit val composite3ArrayTypeMapper = createCompositeArrayJdbcType[Composite3]("composite3").to(_.toList) + registerTypeConverters() + + implicit val composite1TypeMapper: GenericJdbcType[Composite1] = createCompositeJdbcType[Composite1]("composite1") + implicit val composite2TypeMapper: GenericJdbcType[Composite2] = createCompositeJdbcType[Composite2]("composite2") + implicit val composite3TypeMapper: GenericJdbcType[Composite3] = createCompositeJdbcType[Composite3]("composite3") + implicit val composite4TypeMapper: GenericJdbcType[Composite4] = createCompositeJdbcType[Composite4]("composite4") + implicit val c1TypeMapper: GenericJdbcType[C1] = createCompositeJdbcType[C1]("c1") + implicit val c2TypeMapper: GenericJdbcType[C2] = createCompositeJdbcType[C2]("c2") + + implicit val composite1ArrayTypeMapper: DriverJdbcType[List[Composite1]] = createCompositeArrayJdbcType[Composite1]("composite1").to(_.toList) + implicit val composite2ArrayTypeMapper: DriverJdbcType[List[Composite2]] = createCompositeArrayJdbcType[Composite2]("composite2").to(_.toList) + implicit val composite3ArrayTypeMapper: DriverJdbcType[List[Composite3]] = createCompositeArrayJdbcType[Composite3]("composite3").to(_.toList) } override val api: API = new API {} - val plainImplicits = new API with SimpleArrayPlainImplicits { + object plainImplicits extends API with SimpleArrayPlainImplicits { import utils.PlainSQLUtils._ // to support 'nextArray[T]/nextArrayOption[T]' in PgArraySupport { @@ -95,20 +94,20 @@ object PgCompositeSupportSuite { def nextComposite3() = nextComposite[Composite3](r) } - implicit val composite1SetParameter = createCompositeSetParameter[Composite1]("composite1") - implicit val composite1OptSetParameter = createCompositeOptionSetParameter[Composite1]("composite1") - implicit val composite1ArraySetParameter = createCompositeArraySetParameter[Composite1]("composite1") - implicit val composite1ArrayOptSetParameter = createCompositeOptionArraySetParameter[Composite1]("composite1") + implicit val composite1SetParameter: SetParameter[Composite1] = createCompositeSetParameter[Composite1]("composite1") + implicit val composite1OptSetParameter: SetParameter[Option[Composite1]] = createCompositeOptionSetParameter[Composite1]("composite1") + implicit val composite1ArraySetParameter: SetParameter[Seq[Composite1]] = createCompositeArraySetParameter[Composite1]("composite1") + implicit val composite1ArrayOptSetParameter: SetParameter[Option[Seq[Composite1]]] = createCompositeOptionArraySetParameter[Composite1]("composite1") - implicit val composite2SetParameter = createCompositeSetParameter[Composite2]("composite2") - implicit val composite2OptSetParameter = createCompositeOptionSetParameter[Composite2]("composite2") - implicit val composite2ArraySetParameter = createCompositeArraySetParameter[Composite2]("composite2") - implicit val composite2ArrayOptSetParameter = createCompositeOptionArraySetParameter[Composite2]("composite2") + implicit val composite2SetParameter: SetParameter[Composite2] = createCompositeSetParameter[Composite2]("composite2") + implicit val composite2OptSetParameter: SetParameter[Option[Composite2]] = createCompositeOptionSetParameter[Composite2]("composite2") + implicit val composite2ArraySetParameter: SetParameter[Seq[Composite2]] = createCompositeArraySetParameter[Composite2]("composite2") + implicit val composite2ArrayOptSetParameter: SetParameter[Option[Seq[Composite2]]] = createCompositeOptionArraySetParameter[Composite2]("composite2") - implicit val composite3SetParameter = createCompositeSetParameter[Composite3]("composite3") - implicit val composite3OptSetParameter = createCompositeOptionSetParameter[Composite3]("composite3") - implicit val composite3ArraySetParameter = createCompositeArraySetParameter[Composite3]("composite3") - implicit val composite3ArrayOptSetParameter = createCompositeOptionArraySetParameter[Composite3]("composite3") + implicit val composite3SetParameter: SetParameter[Composite3] = createCompositeSetParameter[Composite3]("composite3") + implicit val composite3OptSetParameter: SetParameter[Option[Composite3]] = createCompositeOptionSetParameter[Composite3]("composite3") + implicit val composite3ArraySetParameter: SetParameter[Seq[Composite3]] = createCompositeArraySetParameter[Composite3]("composite3") + implicit val composite3ArrayOptSetParameter: SetParameter[Option[Seq[Composite3]]] = createCompositeOptionArraySetParameter[Composite3]("composite3") } } object MyPostgresProfile1 extends MyPostgresProfile1 @@ -146,7 +145,7 @@ class PgCompositeSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id") def comps = column[List[Composite2]]("comps", O.Default(Nil)) - def * = (id,comps) <> (TestBean.tupled, TestBean.unapply) + def * = (id,comps) <> ((TestBean.apply _).tupled, TestBean.unapply) } val CompositeTests = TableQuery(new TestTable(_)) @@ -154,7 +153,7 @@ class PgCompositeSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id") def comps = column[List[Composite3]]("comps") - def * = (id,comps) <> (TestBean1.tupled, TestBean1.unapply) + def * = (id,comps) <> ((TestBean1.apply _).tupled, TestBean1.unapply) } val CompositeTests1 = TableQuery(new TestTable1(_)) @@ -163,7 +162,7 @@ class PgCompositeSupportSuite extends AnyFunSuite with PostgresContainer { def comps = column[Composite1]("comp") def c2 = column[C2]("c2") - def * = (id,comps,c2) <> (TestBean2.tupled, TestBean2.unapply) + def * = (id,comps,c2) <> ((TestBean2.apply _).tupled, TestBean2.unapply) } val CompositeTests2 = TableQuery(new TestTable2(_)) @@ -171,7 +170,7 @@ class PgCompositeSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id") def comps = column[Option[Composite4]]("comp") - def * = (id, comps) <> (TestBean3.tupled, TestBean3.unapply) + def * = (id, comps) <> ((TestBean3.apply _).tupled, TestBean3.unapply) } val CompositeTests3 = TableQuery(new TestTable3(_)) @@ -294,8 +293,8 @@ class PgCompositeSupportSuite extends AnyFunSuite with PostgresContainer { test("Composite type Plain SQL support") { import MyPostgresProfile1.plainImplicits._ - implicit val getTestBeanResult = GetResult(r => TestBean(r.nextLong(), r.nextArray[Composite2]().toList)) - implicit val getTestBean1Result = GetResult(r => TestBean1(r.nextLong(), r.nextArray[Composite3]().toList)) + implicit val getTestBeanResult: GetResult[TestBean] = GetResult(r => TestBean(r.nextLong(), r.nextArray[Composite2]().toList)) + implicit val getTestBean1Result: GetResult[TestBean1] = GetResult(r => TestBean1(r.nextLong(), r.nextArray[Composite3]().toList)) Await.result(db.run(DBIO.seq( sqlu"create type composite1 as (id int8, txt text, date timestamp, ts_range tsrange)", diff --git a/src/test/scala/com/github/tminglei/slickpg/PgDate2SupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgDate2SupportSuite.scala index 63ce9df6..6be0077e 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgDate2SupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgDate2SupportSuite.scala @@ -43,7 +43,7 @@ class PgDate2SupportSuite extends AnyFunSuite with PostgresContainer { def zone = column[ZoneId]("zone") def * = (id, date, time, dateTime, dateTimeOffset, dateTimeTz, instant, duration, period, zone) <> - (DatetimeBean.tupled, DatetimeBean.unapply) + ((DatetimeBean.apply _).tupled, DatetimeBean.unapply) } val Datetimes = TableQuery[DatetimeTable] @@ -289,7 +289,7 @@ class PgDate2SupportSuite extends AnyFunSuite with PostgresContainer { def * = (id, date, time, dateTime, dateTimeOffset, dateTimeTz, instant, duration, period, zone) <> - (DatetimeOptionBean.tupled, DatetimeOptionBean.unapply) + ((DatetimeOptionBean.apply _).tupled, DatetimeOptionBean.unapply) } val DatetimesOption = TableQuery[DatetimeOptionTable] @@ -360,7 +360,7 @@ class PgDate2SupportSuite extends AnyFunSuite with PostgresContainer { test("Java8 date Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getDateBean = GetResult(r => DatetimeBean( + implicit val getDateBean: GetResult[DatetimeBean] = GetResult(r => DatetimeBean( r.nextLong(), r.nextLocalDate(), r.nextLocalTime(), r.nextLocalDateTime(), r.nextOffsetDateTime(), r.nextZonedDateTime(), r.nextInstant(), r.nextDuration(), r.nextPeriod(), r.nextZoneId())) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgDateSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgDateSupportSuite.scala index 1d1f3dc6..f5d0a4df 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgDateSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgDateSupportSuite.scala @@ -51,7 +51,7 @@ class PgDateSupportSuite extends AnyFunSuite with PostgresContainer { def timestamptz = column[Calendar]("timestamptz") def interval = column[Interval]("interval") - def * = (id, date, time, timestamp, timestamptz, interval) <> (DatetimeBean.tupled, DatetimeBean.unapply) + def * = (id, date, time, timestamp, timestamptz, interval) <> ((DatetimeBean.apply _).tupled, DatetimeBean.unapply) } val Datetimes = TableQuery[DatetimeTable] diff --git a/src/test/scala/com/github/tminglei/slickpg/PgEnumSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgEnumSupportSuite.scala index e5cd1ba5..987f3ecf 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgEnumSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgEnumSupportSuite.scala @@ -4,9 +4,7 @@ import scala.collection.compat._ import scala.collection.compat.immutable.LazyList import scala.concurrent.Await import scala.concurrent.duration._ - -import slick.jdbc.PostgresProfile - +import slick.jdbc.{JdbcType, PostgresProfile} import org.scalatest.funsuite.AnyFunSuite @@ -29,8 +27,8 @@ class PgEnumSupportSuite extends AnyFunSuite with PostgresContainer { def values = _values map (v => (v.toString, v)) toMap } - object Currency extends Enum[Currency] sealed trait Currency extends Currency.Value + object Currency extends Enum[Currency] case object EUR extends Currency case object GBP extends Currency case object USD extends Currency @@ -57,30 +55,30 @@ class PgEnumSupportSuite extends AnyFunSuite with PostgresContainer { /// trait API extends JdbcAPI { - implicit val weekDayTypeMapper = createEnumJdbcType("WeekDay", WeekDays) - implicit val weekDayListTypeMapper = createEnumListJdbcType("weekDay", WeekDays) - implicit val rainbowTypeMapper = createEnumJdbcType("Rainbow", Rainbows, true) - implicit val rainbowListTypeMapper = createEnumListJdbcType("Rainbow", Rainbows, true) + implicit val weekDayTypeMapper: JdbcType[WeekDays.Value] = createEnumJdbcType[WeekDays.type]("WeekDay", WeekDays) + implicit val weekDayListTypeMapper: JdbcType[List[WeekDays.Value]] = createEnumListJdbcType[WeekDays.type]("weekDay", WeekDays) + implicit val rainbowTypeMapper: JdbcType[Rainbows.Value] = createEnumJdbcType[Rainbows.type]("Rainbow", Rainbows, true) + implicit val rainbowListTypeMapper: JdbcType[List[Rainbows.Value]] = createEnumListJdbcType[Rainbows.type]("Rainbow", Rainbows, true) - implicit val weekDayColumnExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder(WeekDays) - implicit val weekDayOptionColumnExtensionMethodsBuilder = createEnumOptionColumnExtensionMethodsBuilder(WeekDays) - implicit val rainbowColumnExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder(Rainbows) - implicit val rainbowOptionColumnExtensionMethodsBuilder = createEnumOptionColumnExtensionMethodsBuilder(Rainbows) + implicit def weekDayColumnExtensionMethodsBuilder(rep: Rep[WeekDays.Value]): EnumColumnExtensionMethods[WeekDays.Value, WeekDays.Value] = createEnumColumnExtensionMethodsBuilder[WeekDays.type](WeekDays).apply(rep) + implicit def weekDayOptionColumnExtensionMethodsBuilder(rep: Rep[Option[WeekDays.Value]]): EnumColumnExtensionMethods[WeekDays.Value, Option[WeekDays.Value]] = createEnumOptionColumnExtensionMethodsBuilder[WeekDays.type](WeekDays).apply(rep) + implicit def rainbowColumnExtensionMethodsBuilder(rep: Rep[Rainbows.Value]): EnumColumnExtensionMethods[Rainbows.Value, Rainbows.Value] = createEnumColumnExtensionMethodsBuilder[Rainbows.type](Rainbows).apply(rep) + implicit def rainbowOptionColumnExtensionMethodsBuilder(rep: Rep[Option[Rainbows.Value]]): EnumColumnExtensionMethods[Rainbows.Value, Option[Rainbows.Value]] = createEnumOptionColumnExtensionMethodsBuilder[Rainbows.type](Rainbows).apply(rep) /// custom types of java enums and algebraic data type (ADT) - implicit val currencyTypeMapper = createEnumJdbcType[Currency]("Currency", _.toString, Currency.values.get(_).get, quoteName = false) - implicit val currencyTypeListMapper = createEnumListJdbcType[Currency]("Currency", _.toString, Currency.values.get(_).get, quoteName = false) - implicit val languagesTypeMapper = createEnumJdbcType[Languages]("Languages", _.name(), Languages.valueOf, quoteName = true) - implicit val languagesTypeListMapper = createEnumListJdbcType[Languages]("Languages", _.name(), Languages.valueOf, quoteName = true) - implicit val genderTypeMapper = createEnumJdbcType[Gender]("Gender", _.repr, Gender.fromString, quoteName = false) - implicit val genderTypeListMapper = createEnumListJdbcType[Gender]("Gender", _.repr, Gender.fromString, quoteName = false) - - implicit val currencyColumnExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder[Currency] - implicit val currencyOptionColumnExtensionMethodsBuilder = createEnumOptionColumnExtensionMethodsBuilder[Currency] - implicit val languagesColumnExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder[Languages] - implicit val languagesOptionColumnExtensionMethodsBuilder = createEnumOptionColumnExtensionMethodsBuilder[Languages] - implicit val genderColumnExtensionMethodsBuilder = createEnumColumnExtensionMethodsBuilder[Gender] - implicit val genderOptionColumnExtensionMethodsBuilder = createEnumOptionColumnExtensionMethodsBuilder[Gender] + implicit val currencyTypeMapper: JdbcType[Currency] = createEnumJdbcType[Currency]("Currency", _.toString, Currency.values.get(_).get, quoteName = false) + implicit val currencyTypeListMapper: JdbcType[List[Currency]] = createEnumListJdbcType[Currency]("Currency", _.toString, Currency.values.get(_).get, quoteName = false) + implicit val languagesTypeMapper: JdbcType[Languages] = createEnumJdbcType[Languages]("Languages", _.name(), Languages.valueOf, quoteName = true) + implicit val languagesTypeListMapper: JdbcType[List[Languages]] = createEnumListJdbcType[Languages]("Languages", _.name(), Languages.valueOf, quoteName = true) + implicit val genderTypeMapper: JdbcType[Gender] = createEnumJdbcType[Gender]("Gender", _.repr, Gender.fromString, quoteName = false) + implicit val genderTypeListMapper: JdbcType[List[Gender]] = createEnumListJdbcType[Gender]("Gender", _.repr, Gender.fromString, quoteName = false) + + implicit def currencyColumnExtensionMethodsBuilder(rep: Rep[Currency]): EnumColumnExtensionMethods[Currency, Currency] = createEnumColumnExtensionMethodsBuilder[Currency].apply(rep) + implicit def currencyOptionColumnExtensionMethodsBuilder(rep: Rep[Option[Currency]]): EnumColumnExtensionMethods[Currency, Option[Currency]] = createEnumOptionColumnExtensionMethodsBuilder[Currency].apply(rep) + implicit def languagesColumnExtensionMethodsBuilder(rep: Rep[Languages]): EnumColumnExtensionMethods[Languages, Languages] = createEnumColumnExtensionMethodsBuilder[Languages].apply(rep) + implicit def languagesOptionColumnExtensionMethodsBuilder(rep: Rep[Option[Languages]]): EnumColumnExtensionMethods[Languages, Option[Languages]] = createEnumOptionColumnExtensionMethodsBuilder[Languages].apply(rep) + implicit def genderColumnExtensionMethodsBuilder(rep: Rep[Gender]): EnumColumnExtensionMethods[Gender, Gender] = createEnumColumnExtensionMethodsBuilder[Gender].apply(rep) + implicit def genderOptionColumnExtensionMethodsBuilder(rep: Rep[Option[Gender]]): EnumColumnExtensionMethods[Gender, Option[Gender]] = createEnumOptionColumnExtensionMethodsBuilder[Gender].apply(rep) } } object MyPostgresProfile1 extends MyPostgresProfile1 @@ -104,7 +102,7 @@ class PgEnumSupportSuite extends AnyFunSuite with PostgresContainer { def weekdays = column[List[WeekDay]]("weekdays") def rainbows = column[List[Rainbow]]("rainbows") - def * = (id, weekday, rainbow, weekdays, rainbows) <> (TestEnumBean.tupled, TestEnumBean.unapply) + def * = (id, weekday, rainbow, weekdays, rainbows) <> ((TestEnumBean.apply _).tupled, TestEnumBean.unapply) } val TestEnums = TableQuery(new TestEnumTable(_)) @@ -125,7 +123,7 @@ class PgEnumSupportSuite extends AnyFunSuite with PostgresContainer { def currencies = column[List[Currency]]("currencies") def languages = column[List[Languages]]("languages") - def * = (id, currency, language, gender, currencies, languages) <> (TestEnumBean1.tupled, TestEnumBean1.unapply) + def * = (id, currency, language, gender, currencies, languages) <> ((TestEnumBean1.apply _).tupled, TestEnumBean1.unapply) } val TestEnums1 = TableQuery(new TestEnumTable1(_)) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgHStoreSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgHStoreSupportSuite.scala index c84e80b3..ab767f2e 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgHStoreSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgHStoreSupportSuite.scala @@ -17,7 +17,7 @@ class PgHStoreSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def hstore = column[Map[String, String]]("hstoreMap", O.Default(Map.empty)) - def * = (id, hstore) <> (MapBean.tupled, MapBean.unapply) + def * = (id, hstore) <> ((MapBean.apply _).tupled, MapBean.unapply) } val HStoreTests = TableQuery[HStoreTestTable] @@ -107,7 +107,7 @@ class PgHStoreSupportSuite extends AnyFunSuite with PostgresContainer { test("Hstore Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getMapBeanResult = GetResult(r => MapBean(r.nextLong(), r.nextHStore())) + implicit val getMapBeanResult: GetResult[MapBean] = GetResult(r => MapBean(r.nextLong(), r.nextHStore())) val b = MapBean(34L, Map("a"->"val1", "b"->"val3", "c"->"321")) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgJsonSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgJsonSupportSuite.scala index 335a20d3..3e87bf95 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgJsonSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgJsonSupportSuite.scala @@ -18,7 +18,7 @@ class PgJsonSupportSuite extends AnyFunSuite with PostgresContainer { def id = column[Long]("id", O.AutoInc, O.PrimaryKey) def json = column[JsonString]("json", O.Default(JsonString(""" {"a":"v1","b":2} """))) - def * = (id, json) <> (JsonBean.tupled, JsonBean.unapply) + def * = (id, json) <> ((JsonBean.apply _).tupled, JsonBean.unapply) } val JsonTests = TableQuery[JsonTestTable] @@ -148,7 +148,7 @@ class PgJsonSupportSuite extends AnyFunSuite with PostgresContainer { test("Json Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getJsonBeanResult = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) + implicit val getJsonBeanResult: GetResult[JsonBean] = GetResult(r => JsonBean(r.nextLong(), r.nextJson())) val b = JsonBean(34L, JsonString(""" { "a":101, "b":"aaa", "c":[3,4,5,9] } """)) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgLTreeSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgLTreeSupportSuite.scala index f42f9211..ef067703 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgLTreeSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgLTreeSupportSuite.scala @@ -19,7 +19,7 @@ class PgLTreeSupportSuite extends AnyFunSuite with PostgresContainer { def path = column[LTree]("path") def treeArr = column[List[LTree]]("tree_arr") - def * = (id, path, treeArr) <> (LTreeBean.tupled, LTreeBean.unapply) + def * = (id, path, treeArr) <> ((LTreeBean.apply _).tupled, LTreeBean.unapply) } val LTreeTests = TableQuery[LTreeTestTable] @@ -166,7 +166,7 @@ class PgLTreeSupportSuite extends AnyFunSuite with PostgresContainer { test("Ltree Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getLTreeBeanResult = GetResult(r => LTreeBean(r.nextLong(), r.nextLTree(), r.nextArray[LTree]().toList)) + implicit val getLTreeBeanResult: GetResult[LTreeBean] = GetResult(r => LTreeBean(r.nextLong(), r.nextLTree(), r.nextArray[LTree]().toList)) val b = LTreeBean(100L, LTree("Top"), List(LTree("Top.Science"), LTree("Top.Collections"))) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgNetSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgNetSupportSuite.scala index fd262d86..10084ac2 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgNetSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgNetSupportSuite.scala @@ -19,7 +19,7 @@ class PgNetSupportSuite extends AnyFunSuite with PostgresContainer { def inet = column[InetString]("inet") def mac = column[Option[MacAddrString]]("mac") - def * = (id, inet, mac) <> (NetBean.tupled, NetBean.unapply) + def * = (id, inet, mac) <> ((NetBean.apply _).tupled, NetBean.unapply) } val NetTests = TableQuery[NetTestTable] @@ -180,7 +180,7 @@ class PgNetSupportSuite extends AnyFunSuite with PostgresContainer { test("net Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getNetBeanResult = GetResult(r => NetBean(r.nextLong(), r.nextIPAddr(), r.nextMacAddrOption())) + implicit val getNetBeanResult: GetResult[NetBean] = GetResult(r => NetBean(r.nextLong(), r.nextIPAddr(), r.nextMacAddrOption())) val b = NetBean(34L, InetString("10.1.0.0/16"), Some(MacAddrString("12:34:56:78:90:ab"))) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgRangeSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgRangeSupportSuite.scala index 57488c43..68e35cbf 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgRangeSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgRangeSupportSuite.scala @@ -39,7 +39,7 @@ class PgRangeSupportSuite extends AnyFunSuite with PostgresContainer { def odtRange = column[Option[Range[OffsetDateTime]]]("odt_range") def ldRange = column[Option[Range[LocalDate]]]("ld_range") - def * = (id, intRange, floatRange, tsRange, ldtRange, odtRange, ldRange) <> (RangeBean.tupled, RangeBean.unapply) + def * = (id, intRange, floatRange, tsRange, ldtRange, odtRange, ldRange) <> ((RangeBean.apply _).tupled, RangeBean.unapply) } val RangeTests = TableQuery[RangeTestTable] @@ -159,7 +159,7 @@ class PgRangeSupportSuite extends AnyFunSuite with PostgresContainer { test("Range Plain SQL support") { import MyPostgresProfile.plainAPI._ - implicit val getRangeBeanResult = GetResult(r => + implicit val getRangeBeanResult: GetResult[RangeBean] = GetResult(r => RangeBean(r.nextLong(), r.nextIntRange(), r.nextFloatRange(), r.nextTimestampRangeOption(), r.nextLocalDateTimeRangeOption(), r.nextOffsetDateTimeRangeOption(), r.nextLocalDateRangeOption())) diff --git a/src/test/scala/com/github/tminglei/slickpg/PgSearchSupportSuite.scala b/src/test/scala/com/github/tminglei/slickpg/PgSearchSupportSuite.scala index 6945d802..410c8102 100644 --- a/src/test/scala/com/github/tminglei/slickpg/PgSearchSupportSuite.scala +++ b/src/test/scala/com/github/tminglei/slickpg/PgSearchSupportSuite.scala @@ -23,7 +23,7 @@ class PgSearchSupportSuite extends AnyFunSuite with PostgresContainer { def search = column[TsVector]("search") def comment = column[String]("comment") - def * = (id, text, search, comment) <> (TestBean.tupled, TestBean.unapply) + def * = (id, text, search, comment) <> ((TestBean.apply _).tupled, TestBean.unapply) } val Tests = TableQuery[TestTable] @@ -160,7 +160,7 @@ class PgSearchSupportSuite extends AnyFunSuite with PostgresContainer { case class SearchBean(id: Long, tVec: TsVector, tQ: TsQuery) - implicit val getSearchBeanResult = GetResult(r => SearchBean(r.nextLong(), r.nextTsVector(), r.nextTsQuery())) + implicit val getSearchBeanResult: GetResult[SearchBean] = GetResult(r => SearchBean(r.nextLong(), r.nextTsVector(), r.nextTsQuery())) val b = SearchBean(101L, TsVector("'ate' 'cat' 'fat' 'rat'"), TsQuery("'rat'")) diff --git a/src/test/scala/com/github/tminglei/slickpg/package.scala b/src/test/scala/com/github/tminglei/slickpg/package.scala index 29199870..2a5963aa 100644 --- a/src/test/scala/com/github/tminglei/slickpg/package.scala +++ b/src/test/scala/com/github/tminglei/slickpg/package.scala @@ -1,8 +1,8 @@ package com.github.tminglei import java.util.concurrent.Executors -import scala.concurrent.ExecutionContext +import scala.concurrent.{ExecutionContext, ExecutionContextExecutorService} package object slickpg { - implicit val testExecContext = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) + implicit val testExecContext: ExecutionContextExecutorService = ExecutionContext.fromExecutorService(Executors.newFixedThreadPool(4)) }