tminglei / slick-pg

Slick extensions for PostgreSQL
BSD 2-Clause "Simplified" License
838 stars 180 forks source link

pgArray with arbitrary type (use MappedColumnType instead of SimpleArrayListJdbcType) #86

Open strelec opened 10 years ago

strelec commented 10 years ago
  1. I got this error when trying to have a List of a custom mapped type.
[error] /home/rok/web/Tarok/app/models/db/Round.scala:31: could not find implicit value for parameter tm: scala.slick.ast.TypedType[List[models.Card]]
[error]     def talon = column[List[Card]]("talon")
[error]                                   ^

Card class has proper MappedColumnType in scope.

    implicit val mapper = MappedColumnType.base[Card, Byte](
        Deck.full.indexOf(_).toByte,
        pos => Deck.full.apply(pos.toInt)
    )
  1. I am also not sure List[List[...]] works. Does it?
strelec commented 10 years ago

The way to get it working is to create implicits in the driver class. However, that is unintuitive. If possible, code should be changed to use above implicit instead.

    trait MyArrayImplicits extends ArrayImplicits {
        implicit val cardWrapper = new SimpleArrayListJdbcType[Card]("smallint").basedOn[Short](
            Deck.full.indexOf(_).toShort,
            pos => Deck.full.apply(pos.toShort)
        )
    }
tminglei commented 10 years ago

@strelec card[] is different type to card, that's why we should declare a type mapper for card[].

But, if you mean, why slick-pg not to declare an array type mapper automatically for you based on existing base type mapper when necessary? The answer is, it can but it shouldn't, since we shouldn't create too much duplicated type mapper instances.

But, of course, if a way that can automatically create single array type mapper was found, we should employ it.

strelec commented 10 years ago

Ok, let's resolve this bug, too. The problem is the duplication of code.

  1. I have this code in companion object:
object Card {
    import play.api.db.slick.Config.driver.simple._
    implicit val mapper = MappedColumnType.base[Card, Byte](
        Deck.full.indexOf(_).toByte,
        pos => Deck.full(pos)
    )
}
  1. I have this code in the implicits:
    trait MyArrayImplicits extends ArrayImplicits {
        implicit val cardWrapper = new SimpleArrayListJdbcType[Card]("smallint").basedOn[Byte](
            Deck.full.indexOf(_).toByte,
            pos => Deck.full(pos)
        )
    }

There is clearly a duplication of logic present. What do you think?

tminglei commented 10 years ago

As we know, in general a static object should be hold by a val variable, so it's difficult to generate a type mapper dynamically and keep it static at the same time.

And, from my opinion, if a little inconvenience from super user, who setup environment for a project and ease other team members, can bring up obvious performance improvement, it doesn't matter.

So if we can't find a simple way to resolve this problem, I'd like to leave it go.