Play Framework 2.0 правильный способ представления набора в запросе с использованием Anorm

Я пытаюсь вернуть список результатов с помощью Anorm, используя запрос, который возвращает совпадающие строки для набора идентификаторов. Например.

select *
from example
where id in (1,2,3,4,5)

Если я попытаюсь

SQL(
    """
      select *
      from example 
      where id in ({ids})
    """
  ).on('ids -> ids).as(int("id") ~ str("name") *)

где ids — это строка «1,2,3,4,5», она вернет только первую строку. Как правильно ввести набор идентификаторов?


person Matthew Pickering    schedule 07.04.2013    source источник


Ответы (1)


Нет простого способа сделать это AFAIK.

Вот как я это решил:

def findSomething(ids: String) = {
  // Split up the comma separated values
  val sids = ids split ","
  // Create a list of keys (id0, id1, id2, ...)
  val keys = for ( i <- 0 until sids.size ) yield ("id" + i)
  // Create a seq of parameterized values
  val values = sids map (toParameterValue(_))

  // Now zip together the keys and values into list of tuples
  val params = keys zip values

  DB.withConnection { implicit connection =>
    SQL(
      """
        select *
        from example 
        where id in ({%s})
      """.format(keys.mkString("},{"))
    ).on(
      params: _*
    ).as(
      int("id") ~ str("name") *
    )
  }
}

Примечание
Важнейшей частью здесь является форматирование строки в операторе SQL. Он уязвим для внедрения SQL, если у вас нет полного контроля над входными параметрами.

person maba    schedule 08.04.2013
comment
Здорово! Спасибо за информацию, мне кажется, что я что-то не так делаю. - person Matthew Pickering; 08.04.2013
comment
Спасибо, но это все еще немного сумасшествие, и anorm нуждается в поддержке параметризованных последовательностей. Не говоря уже о том, что использование метода привязки scala noob, ожидаемого к работе со строками, создает в регистраторе абсолютно корректный SQL, но молча терпит неудачу. - person notbrain; 10.04.2013
comment
@notbrain Много раз это обсуждалось в команде разработчиков Play, здесь, здесь и здесь для начинающих. Но я полностью согласен с вами, что это должно быть исправлено. Мой ответ — это всего лишь один из способов обойти недостатки anorm и IN. - person maba; 10.04.2013
comment
Спасибо за ссылки; моя плохая привычка, когда я вижу, что им больше года, я склонен их не замечать :). Также путаница 2.1 и 2.0. Не уверен, почему предложение IN() и автоматическая параметризация последовательностей считаются таким странным запросом. - person notbrain; 11.04.2013