0
votes

I have the following code that includes a case class(MyEmail), the related Slick class (MyEmailDB) and implicit functions to convert LocalDateTime. Problem is that def * = function is throwing a compilation error. If I remove one of the implicit functions the program compiles, but how to fix this?

case class MyEmail (sk: Int, subject: String, message: String, 
                    createTS: LocalDateTime, updateTS: Option[LocalDateTime])

class MyEmailDB(tag: Tag) extends Table[MyEmail](tag, "emails") {

    def sk = column[Int]("sk", O.PrimaryKey, O.AutoInc)
    def subject = column[String]("subject")
    def message = column[String]("message")
    def createTS = column[LocalDateTime]("create_ts")(localDateTimeColumnType)
    def updateTS = column[Option[LocalDateTime]]("update_ts")(localDateTimeColumnType2)

    def * = (sk, subject, message, createTS, updateTS) <> ((MyEmail.apply _).tupled, MyEmail.unapply)  // <-- this line throws the compilation error

    implicit val localDateTimeColumnType = MappedColumnType.base[LocalDateTime, Timestamp](
     {
        case localDateTime => Timestamp.valueOf(localDateTime)
     },{
        ts => ts.toLocalDateTime
     }
   )

   implicit val localDateTimeColumnType2 = MappedColumnType.base[Option[LocalDateTime], Timestamp](
     {
        case Some(localDateTime) => Timestamp.valueOf(localDateTime)
        case None => null
     },{
        ts => if (ts != null) Some(ts.toLocalDateTime) else None
     }
   )   
}

And the error is:

◾Implicit conversion found: ⇒ anyToToShapedValue(): slick.lifted.ToShapedValue[(slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[String], slick.lifted.Rep[java.time.LocalDateTime])] ◾not enough arguments for method <>: (implicit evidence$3: scala.reflect.ClassTag[tasks.addit.email.MyEmail], implicit shape: slick.lifted.Shape[_ <: slick.lifted.FlatShapeLevel, (slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[String], slick.lifted.Rep[java.time.LocalDateTime]), (Int, String, String, java.time.LocalDateTime, Option[java.time.LocalDateTime]), _])slick.lifted.MappedProjection[tasks.addit.email.MyEmail,(Int, String, String, java.time.LocalDateTime, Option[java.time.LocalDateTime])]. Unspecified value parameter shape. ◾implements slick.lifted.AbstractTable.$times ◾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: slick.lifted.FlatShapeLevel Source type: (slick.lifted.Rep[Int], slick.lifted.Rep[String], slick.lifted.Rep[String], slick.lifted.Rep[java.time.LocalDateTime]) Unpacked type: (Int, String, String, java.time.LocalDateTime, Option[java.time.LocalDateTime]) Packed type: Any

1

1 Answers

1
votes

Giving explicit return type as BaseColumnType[LocalDateTime] for the implicit solved the compilation error

Declare the implicit with the explicit return type.

You can improve the code bit more for clarity.

  implicit val localDateTimeColumnType: BaseColumnType[LocalDateTime] = MappedColumnType.base[LocalDateTime, Timestamp](Timestamp.valueOf, _.toLocalDateTime)

  case class MyEmail(sk: Int, subject: String, message: String,
    createTS: LocalDateTime, updateTS: Option[LocalDateTime])

  class MyEmailDB(tag: Tag) extends Table[MyEmail](tag, "emails") {

    def sk = column[Int]("sk", O.PrimaryKey, O.AutoInc)
    def subject = column[String]("subject")
    def message = column[String]("message")
    def createTS = column[LocalDateTime]("create_ts")
    def updateTS = column[Option[LocalDateTime]]("update_ts")

    def * = (sk, subject, message, createTS, updateTS) <> ((MyEmail.apply _).tupled, MyEmail.unapply)
  }

Note you do not need special implicit for Option[LocalDateTime]