Anorm не работает в PostgreSQL 9.0. - PullRequest
3 голосов
/ 20 марта 2012

Я пытаюсь создать страницу списка, подобную той, что в образце "Компьютеры". Моя среда - Play 2.0 и PostrgreSQL 9.0

В моем объекте User есть следующий метод:

 def list(page: Int = 0, pageSize: Int = 10, orderBy: Int = 1, filter: String = "%"): Page[User] = {
    val offset = pageSize * page
    val mode = if (orderBy > 0) "ASC NULLS FIRST" else "DESC NULLS LAST"

    Logger.debug("Users.list with params: page[%d] pageSize[%d] orderBy[%d] filter[%s] order[%s]".format(page, pageSize, orderBy, filter, mode))

    DB.withConnection {
      implicit connection =>

        val users = SQL(
          """
            select * from publisher
            where name ilike {filter}
            order by {orderBy} %s
            limit {pageSize} offset {offset}
          """.format(mode)
        ).on(
          'pageSize -> pageSize,
          'offset -> offset,
          'filter -> filter,
          'orderBy -> scala.math.abs(orderBy)
        ).as(User.simple *)

        val totalRows = SQL(
          """
            select count(*) from publisher
            where name like {filter}
          """
        ).on(
          'filter -> filter
        ).as(scalar[Long].single)

        Page(users, page, offset, totalRows)
    }

  }

Неважно, какое значение 'orderBy' я предоставляю, заказ всегда основан на идентификаторе сущностей.

Запрос, сгенерированный Anorm, является допустимым PostgreSQL, и он отлично работает при непосредственном запуске к базе данных. Но похоже, что анализатор Anorm игнорировал порядок, в котором возвращаются результаты, и вместо этого возвращает список, упорядоченный по 'id'.

Я даже пытался упростить запрос до "select * from publisher order by 2 ASC/DESC", но ничего не исправлено, порядок возврата игнорируется Anorm.

Любое предложение о том, как решить эту проблему?

1 Ответ

4 голосов
/ 21 марта 2012

Благодаря Гийому в списке рассылки Play я нашел обходной путь.

Все заполнители работают, кроме одного в порядке. Хуже всего то, что когда вы прослеживаете логи, драйвер генерирует правильный запрос, а PostgreSQL получает его. Я не уверен, в чем дело, очень запутанно, но если я уберу этот заполнитель, он просто сработает.

Депрессия: (

Я решил это так:

val users = SQL(
  """
    select * from publisher
    where name ilike {filter}
    order by %d %s
    limit {pageSize} offset {offset}
  """.format(scala.math.abs(orderBy), mode)
).on(
  'pageSize -> pageSize,
  'offset -> offset,
  'filter -> filter
).as(User.simple *)

Теперь вы будете кричать "SQL INJECTION". Расслабьтесь. Хотя это может быть как-то возможно, orderBy является целым числом (которое мы превращаем в значение abs для большей безопасности). Если вы попытаетесь вызвать контроллер, предоставляющий orderBy строку, Play вернет ошибку 404. Так что разрешены только целые числа. И если нет столбца, соответствующего данному целому числу, order by игнорируется. Так что не идеально, но не так плохо.

...