2

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

4
  • This is just a guess, I'm new to scala & anorm, but have you tried Seq[String] ? Commented Mar 21, 2014 at 1:17
  • I tried Seq and List. Both the same. I just found a solution that is creating a custom extractor for the parser. Commented Mar 21, 2014 at 1:25
  • Could you post it? I'm sure it would be helpful to others, including, but not limited to me :) Commented Mar 21, 2014 at 1:28
  • sure, I will after finished the codes and tested it to make sure that it works properly. Thanks. Commented Mar 21, 2014 at 1:30

3 Answers 3

5

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)
  }
Sign up to request clarification or add additional context in comments.

Comments

4

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.

1 Comment

Awesome!!!! Until 2.4 comes out (which I believe will have support for arrays) this is and will work nicely!!!!
0

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

Best,

2 Comments

PR is merged on master
As you can see in test/specs, feature is included in latest sources: github.com/playframework/playframework/blob/master/framework/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.