It seems no easy way to use "in" clause in anorm:
val ids = List("111", "222", "333")
val users = SQL("select * from users where id in ({ids})").on('ids-> ???).as(parser *)
How to replace the ???
part?
I tried:
on('ids -> ids)
on('ids -> ids.mkString("'","','","'"))
on('ids -> ids.mkString("','")
But none works.
I see in the discussion the exactly same problem: https://groups.google.com/d/topic/play-framework/qls6dhhdayc/discussion, the author has a complex solution:
val params = List(1, 2, 3)
val paramsList = for ( i <- 0 until params.size ) yield ("userId" + i)
// ---> results in List("userId0", "userId1", "userId2")
User.find("id in ({%s})"
// produces "id in ({userId0},{userId1},{userId2})"
.format(paramsList.mkString("},{"))
// produces Map("userId0" -> 1, "userId1" -> 2, ...)
.on(paramsList.zip(params))
.list()
This is too much complicated.
Is there any easier way? Or should play provide something to make it easier?
Maybe it's too late but here is a tip for using custom string interpolation that also works for solve the problem of IN clause.
I have implemented a helper class to define a string interpolation. You can see it below, and you can simply copy and paste, but first let's see how you can use it.
Instead of write something
You can simply write:
So using string interpolation it's more concise and easier to read.
And for the case of using the IN clause, you can write:
Or for your example:
For more information about string interpolation, check this link
The code for this implicit class is the following:
Anorm now supports such a case (and more) since 2.3: "Using multi-value parameter"
Back to initial example it gives:
Nailed it! There haven't really been any more updates on this thread, but it seems to still be relevant. Because of that, and because there isn't an answer, I thought I'd throw mine in for consideration.
Anorm doesn't support 'IN' clauses. I doubt they ever will. There's nothing you can do to make them work, I even read a post where anorm specifically took out those clauses because they made Anorm feel 'like an ORM'.
It's fairly easy, however, to wrap the SqlQuery in a short class that supports the IN clause, and then convert that class into a SqlQuery when needed.
Instead of pasting the code in here, because it gets a little long, here is the link to my blog, where I've posted the code and how to use it.
In clause with Anorm
Basically, when you have the code from my blog, your statements look like this:
I had the same problem recently. Unfortunately there doesn't seem to be a way without using string interpolation and thus vulnerable to SQL injection.
What I ended up doing was kinda sanitizing it by transforming it to a list of ints and back: