Question

I am using postgresql which supports array column field. To parse a row, I use this parser. It has error at the Array object. I guess I did it wrongly.

case class ServiceRequest(
  id: Pk[Long],
  firstname: String,
  lastname: String,
  images: Array[String])

val parser: RowParser[ServiceRequest] = {
    get[Pk[Long]]("id") ~
      get[String]("firstname") ~
      get[String]("lastname") ~
      Error here >>> get[Array[String]]("images") map {
        case id ~ firstname ~ lastname ~ images=>
          ServiceRequest(id, firstname, lastname, images)
      }
  }

Thanks

Was it helpful?

Solution 2

I have solved my problem by adding this converter:

implicit def rowToStringArray: Column[Array[String]] = Column.nonNull { (value, meta) =>
    val MetaDataItem(qualified, nullable, clazz) = meta
    value match {
      case o: java.sql.Array => Right(o.getArray().asInstanceOf[Array[String]])
      case _ => Left(TypeDoesNotMatch("Cannot convert " + value + ":" + value.asInstanceOf[AnyRef].getClass))
    }
  }

The converter transforms data type from postgresql's jdbc to java's data type for the parser in SELECT function. When you insert, you need another converter to convert from java's data type to postgresql's jdbc.

OTHER TIPS

The Array[T] type is now natively supported in play 2.4.x, your don't have to roll your own converters. But, it's still not nice to work with insert or update statements like:

def updateTags(id: Long, values: Seq[String]):Int = {
    DB.withConnection { implicit conn =>
      SQL("UPDATE entries SET tags = {value} WHERE id = {id}")
        .on('value -> values, 'id -> id).executeUpdate
} 

will give you an error

play - Cannot invoke the action, eventually got an error: org.postgresql.util.PSQLException: ERROR: syntax error at or near "$2"

Put it simply, you should create the PreparedStatement using java.sql.Array type:

on('value -> conn.createArrayOf("varchar", value.asInstanceOf[Array[AnyRef]]), ...

As of now (play 2.4-M1), java.sql.Array is not converted to ParameterValue by default, which means SQL(...).on(`arr -> values:java.sql.Array ) still gives a compilation error, you need another implicit conversion to make it compiling:

  implicit object sqlArrayToStatement extends ToStatement[java.sql.Array] {
    def set(s: PreparedStatement, i: Int, n: java.sql.Array) = s.setArray(i, n)
  }

There is currently a pullrequest to add support for java.sql.Array as column mapping: https://github.com/playframework/playframework/pull/3062 .

Best,

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top