Let's say I have a case class called Blarg
consisting of properties with primitive types:
case class Blarg(
x: String,
y: Int
)
Blarg
s are used in various classes, sometimes as Option[Blarg]
, sometimes as List[Blarg]
, and those classes are persisted. We also have a case class called OptionalComplexThing
containing a property of type Option[Blarg]
:
case class OptionalComplexThing(
one: String,
maybeInt: Option[Int],
maybeBlarg: Option[Blarg],
id: Option[Long] = None
)
The problem is how to create a default MappedProjection
containing the appropriate sub-projection. Notice the blarg
MappedProjection
below. I want to be able to transform the blarg
MappedProjection
so all its Column
s are Option
s. I don't want to hard-code this example - there should be a generic way to do this using combinators.
class _OptionalComplexThings(tag: Tag) extends Table[OptionalComplexThing](tag, "optional_complex_thing") {
def one = column[String]("one")
def maybeInt = column[Option[Int]]("maybe_int") // specifying O.Nullable makes no difference
def id = column[Option[Long]]("id", O.PrimaryKey, O.AutoInc)
// Blarg fields need to have their lifted types remapped according to MappedProjection usage.
// Notice OptionalComplexThing's maybeBlarg property is an Option[Blarg].
def x = column[String]("x") // want to map to column[Option[String]]("x")
def y = column[Int]("y") // want to map to column[Option[String]]("y")
def blarg = (x, y) <> (Blarg.tupled, Blarg.unapply)
def * = (one, maybeInt, Option(blarg), id) <> (OptionalComplexThing.tupled, OptionalComplexThing.unapply)
/* Error:(23, 46) No matching Shape found.
Slick does not know how to map the given types.
Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List).
Required level: scala.slick.lifted.FlatShapeLevel
Source type: (scala.slick.lifted.Column[String], scala.slick.lifted.Column[Option[Int]], Option[scala.slick.lifted.MappedProjection[Blarg,(String, Int)]], scala.slick.lifted.Column[Option[Long]])
Unpacked type: (String, Option[Int], Option[Blarg], Option[Long])
Packed type: Any
def * = (one, maybeInt, Option(blarg), id) <> (OptionalComplexThing.tupled, OptionalComplexThing.unapply)
^ */
}
Here is a a GitHub project that demonstrates the question.