2

I am trying to define a nullable date field in postgres, while using anorm as connection to the database.

I am trying to update an entry:

def update(id: Long, startTime: Option[LocalDate]){
   SQL("""UPDATE my_table
        |SET start_date = {start_date}
        |WHERE id = {id}
      """.stripMargin)
      .on(
        'id ->id,
        'start_date -> startDate,
      ).executeUpdate()
 }

But I get a compilation error, looks like anorm can't handle Option[DateTime], although when I configured a parser it works form me:

val parser: RowParser[Info] = {
  get[Long]("id") ~
  get[Option[DateTime]]("start_date") map {
  case id ~ startTime => Info(id, startDate)
}

}

What am I missing here? Thanks!

Tomer
  • 2,398
  • 1
  • 23
  • 31
  • 1
    Try adding a `import JodaParameterMetaData._` – Lars Arnbak Nov 16 '15 at 08:34
  • @Lars Arnbak what about Option[LocalDate], need to import something else? – Tomer Nov 16 '15 at 08:57
  • or Option[LocalDateTime] – Tomer Nov 16 '15 at 09:09
  • Possible duplicate of [Migrating to anorm2.4 (with play 2.4): ToStatement\[T\] and ToStatement\[Option\[T\]\]](http://stackoverflow.com/questions/33809995/migrating-to-anorm2-4-with-play-2-4-tostatementt-and-tostatementoptiont) – cchantep Nov 21 '15 at 00:49
  • @cchantep this did not fix my problem. You must add the relevant implicit definitions for anorm to be able to process LocalDate. I edited my solution also to include the ParameterMetaData class. – Tomer Nov 22 '15 at 08:47
  • Possible duplicate of [Play + Anorm + Postgres - load json value into a case class](http://stackoverflow.com/questions/33924041/play-anorm-postgres-load-json-value-into-a-case-class) – Tomer Nov 26 '15 at 06:44

2 Answers2

0

I added my own implicit definitions:

implicit def rowToLocalDate: Column[LocalDate] = Column.nonNull {(value, meta) =>
   val MetaDataItem(qualified, nullable, clazz) = meta
   value match {
      case ts: java.sql.Timestamp => Right(new LocalDate(ts.getTime))
      case d: java.sql.Date => Right(new LocalDate(d.getTime))
      case str: java.lang.String => Right(fmt.parseLocalDate(str))
      case _ => Left(TypeDoesNotMatch("Cannot convert " + value + ":" + value.asInstanceOf[AnyRef].getClass) )
}

}

implicit val localDateToStatement = new ToStatement[LocalDate] {
    def set(s: java.sql.PreparedStatement, index: Int, aValue: LocalDate): Unit = {
       s.setTimestamp(index, new java.sql.Timestamp(aValue.toDateTimeAtStartOfDay().getMillis()))
}

}

And the relevant ParameterMetaData

implicit object LocalDateClassMetaData extends  ParameterMetaData[LocalDate] {
   val sqlType = ParameterMetaData.DateParameterMetaData.sqlType
   val jdbcType = ParameterMetaData.DateParameterMetaData.jdbcType
}

That made the trick

Tomer
  • 2,398
  • 1
  • 23
  • 31
  • Yea that will work. However should be able to do `val parser: RowParser[Info] = { import JodaParameterMetaData._ get[Long]("id") ~ get[Option[DateTime]]("start_date") map { case id ~ startTime => Info(id, startDate) }` And have the types you need. – Lars Arnbak Nov 16 '15 at 10:02
0

Related question, Anorm compare/search by java.time LocalDateTime what it worked for me is just update to new version (not-yet-release-one)

Community
  • 1
  • 1
ses
  • 13,174
  • 31
  • 123
  • 226