Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
lihaoyi committed Aug 29, 2024
1 parent 353776f commit 819a3ce
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 5 deletions.
13 changes: 12 additions & 1 deletion scalasql/core/src/TypeMapper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import java.util.UUID
* Defaults are provided for most common Scala primitives, but you can also provide
* your own by defining an `implicit val foo: TypeMapper[T]`
*/
trait TypeMapper[T] {
trait TypeMapper[T] {outer =>

/**
* The JDBC type of this type. Used for `setNull` which needs to know the
Expand All @@ -51,6 +51,17 @@ trait TypeMapper[T] {
* How to insert a value of type [[T]] into a `PreparedStatement`
*/
def put(r: PreparedStatement, idx: Int, v: T): Unit

/**
* Create a new `TypeMapper[V]` based on this `TypeMapper[T]` given the
* two conversion functions `f: V => T`, `g: T => V`
*/
def bimap[V](f: V => T, g: T => V): TypeMapper[V] = new TypeMapper[V]{
def jdbcType: JDBCType = outer.jdbcType
override def castTypeString: String = outer.castTypeString
def get(r: ResultSet, idx: Int): V = g(outer.get(r, idx))
def put(r: PreparedStatement, idx: Int, v: V): Unit = outer.put(r, idx, f(v))
}
}

object TypeMapper {
Expand Down
49 changes: 45 additions & 4 deletions scalasql/test/src/WorldSqlTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1420,20 +1420,62 @@ object WorldSqlTests extends TestSuite {
SqlStr.Interp.TypeInterp[CityId](CityId(1337))
// +DOCS

case class City2[T[_]](
case class City[T[_]](
id: T[CityId],
name: T[String],
countryCode: T[String],
district: T[String],
population: T[Long]
)

object City extends Table[City]() {
override def tableName: String = "city"
}
db.run(
City.insert.columns(
_.id := CityId(31337),
_.name := "test",
_.countryCode := "XYZ",
_.district := "district",
_.population := 1000000
)
)

db.run(City.select.filter(_.id === 31337).single) ==>
City[Sc](CityId(31337), "test", "XYZ", "district", 1000000)
// -DOCS

// You can also use `TypeMapper#bimap` for the common case where you want the
// new `TypeMapper` to behave the same as an existing `TypeMapper`, just with
// conversion functions to convert back and forth between the old type and new type:

case class CityId2(value: Int)

object CityId2 {
implicit def tm: TypeMapper[CityId2] = implicitly[TypeMapper[Int]].bimap[CityId2](
city => city.value,
int => CityId2(int)
)
}

// -DOCS
// Note sure why this is required, probably a Scalac bug
SqlStr.Interp.TypeInterp[CityId2](CityId2(1337))
// +DOCS
case class City2[T[_]](
id: T[CityId2],
name: T[String],
countryCode: T[String],
district: T[String],
population: T[Long]
)

object City2 extends Table[City2]() {
override def tableName: String = "city"
}
db.run(
City2.insert.columns(
_.id := CityId(31337),
_.id := CityId2(31337),
_.name := "test",
_.countryCode := "XYZ",
_.district := "district",
Expand All @@ -1442,8 +1484,7 @@ object WorldSqlTests extends TestSuite {
)

db.run(City2.select.filter(_.id === 31337).single) ==>
City2[Sc](CityId(31337), "test", "XYZ", "district", 1000000)
// -DOCS
City2[Sc](CityId2(31337), "test", "XYZ", "district", 1000000)
}
test("customTableColumnNames") {
// +DOCS
Expand Down

0 comments on commit 819a3ce

Please sign in to comment.