Skip to content

Commit 819a3ce

Browse files
committed
wip
1 parent 353776f commit 819a3ce

File tree

2 files changed

+57
-5
lines changed

2 files changed

+57
-5
lines changed

scalasql/core/src/TypeMapper.scala

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ import java.util.UUID
2929
* Defaults are provided for most common Scala primitives, but you can also provide
3030
* your own by defining an `implicit val foo: TypeMapper[T]`
3131
*/
32-
trait TypeMapper[T] {
32+
trait TypeMapper[T] {outer =>
3333

3434
/**
3535
* The JDBC type of this type. Used for `setNull` which needs to know the
@@ -51,6 +51,17 @@ trait TypeMapper[T] {
5151
* How to insert a value of type [[T]] into a `PreparedStatement`
5252
*/
5353
def put(r: PreparedStatement, idx: Int, v: T): Unit
54+
55+
/**
56+
* Create a new `TypeMapper[V]` based on this `TypeMapper[T]` given the
57+
* two conversion functions `f: V => T`, `g: T => V`
58+
*/
59+
def bimap[V](f: V => T, g: T => V): TypeMapper[V] = new TypeMapper[V]{
60+
def jdbcType: JDBCType = outer.jdbcType
61+
override def castTypeString: String = outer.castTypeString
62+
def get(r: ResultSet, idx: Int): V = g(outer.get(r, idx))
63+
def put(r: PreparedStatement, idx: Int, v: V): Unit = outer.put(r, idx, f(v))
64+
}
5465
}
5566

5667
object TypeMapper {

scalasql/test/src/WorldSqlTests.scala

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,20 +1420,62 @@ object WorldSqlTests extends TestSuite {
14201420
SqlStr.Interp.TypeInterp[CityId](CityId(1337))
14211421
// +DOCS
14221422

1423-
case class City2[T[_]](
1423+
case class City[T[_]](
14241424
id: T[CityId],
14251425
name: T[String],
14261426
countryCode: T[String],
14271427
district: T[String],
14281428
population: T[Long]
14291429
)
14301430

1431+
object City extends Table[City]() {
1432+
override def tableName: String = "city"
1433+
}
1434+
db.run(
1435+
City.insert.columns(
1436+
_.id := CityId(31337),
1437+
_.name := "test",
1438+
_.countryCode := "XYZ",
1439+
_.district := "district",
1440+
_.population := 1000000
1441+
)
1442+
)
1443+
1444+
db.run(City.select.filter(_.id === 31337).single) ==>
1445+
City[Sc](CityId(31337), "test", "XYZ", "district", 1000000)
1446+
// -DOCS
1447+
1448+
// You can also use `TypeMapper#bimap` for the common case where you want the
1449+
// new `TypeMapper` to behave the same as an existing `TypeMapper`, just with
1450+
// conversion functions to convert back and forth between the old type and new type:
1451+
1452+
case class CityId2(value: Int)
1453+
1454+
object CityId2 {
1455+
implicit def tm: TypeMapper[CityId2] = implicitly[TypeMapper[Int]].bimap[CityId2](
1456+
city => city.value,
1457+
int => CityId2(int)
1458+
)
1459+
}
1460+
1461+
// -DOCS
1462+
// Note sure why this is required, probably a Scalac bug
1463+
SqlStr.Interp.TypeInterp[CityId2](CityId2(1337))
1464+
// +DOCS
1465+
case class City2[T[_]](
1466+
id: T[CityId2],
1467+
name: T[String],
1468+
countryCode: T[String],
1469+
district: T[String],
1470+
population: T[Long]
1471+
)
1472+
14311473
object City2 extends Table[City2]() {
14321474
override def tableName: String = "city"
14331475
}
14341476
db.run(
14351477
City2.insert.columns(
1436-
_.id := CityId(31337),
1478+
_.id := CityId2(31337),
14371479
_.name := "test",
14381480
_.countryCode := "XYZ",
14391481
_.district := "district",
@@ -1442,8 +1484,7 @@ object WorldSqlTests extends TestSuite {
14421484
)
14431485

14441486
db.run(City2.select.filter(_.id === 31337).single) ==>
1445-
City2[Sc](CityId(31337), "test", "XYZ", "district", 1000000)
1446-
// -DOCS
1487+
City2[Sc](CityId2(31337), "test", "XYZ", "district", 1000000)
14471488
}
14481489
test("customTableColumnNames") {
14491490
// +DOCS

0 commit comments

Comments
 (0)