Anorm возвращает 0 результатов, а psql возвращает 2 результата

Я включаю панель поиска через AJAX, которая пропускает выбранный фильтр (переключатель), который относится к столбцу базы данных и строке поиска для всего, что введено в панель поиска. Используемый мной код scala/play/anorm:

def searchDB(searchString: String, filter: String): List[DatabaseResult] = {
DB.withConnection { implicit c =>
  SQL(
    """
      SELECT name, email, emailsecondary, picture, linkedin, title, company, companylink, companydesc, location, github, stackru, twitter, blog
      FROM mailinglistperson
      WHERE {filter} LIKE '%{searchString}%'
    """).on(
          'filter -> filter,
          'searchString -> searchString
    ).as(databaseResultParser.*)
}

}

Когда я запускаю запрос к базе данных (PostgreSQL), используя psql который изоморфен приведенному выше анормальному коду, он возвращает 2 результата, а именно:

select id, name, email from mailinglistperson where company like '%kixer%';

Но код anorm возвращает 0 результатов, когда передал те же самые значения (я проверил значения через println)

РЕДАКТИРОВАТЬ: Когда я переключаю код anorm для использования String Interpolation, я получаю:

[error] - play.core.server.netty.PlayDefaultUpstreamHandler - Cannot invoke the action
 java.lang.RuntimeException: No parameter value for placeholder: 3

РЕДАКТИРОВАТЬ 2: Я также попытался передать '%...%' вместе с searchString в LIKE и все еще получил 0 результатов.

1 ответ

Решение

Есть две проблемы - имя столбца и значение фильтра


Что касается значения фильтра: вы должны опустить одиночные галочки в команде SQL, и вы должны передать заполнитель "%" в аргументе. Тики обрабатываются автоматически в случае строки.


Что касается имени столбца: это похоже на строковый параметр, поэтому снова тики обрабатываются также автоматически:

[debug] cjbPreparedStatementHandle - выберите... из... где "фильтр" похож на "%aaa%"

Одно из решений: использовать нормальную интерполяцию строк s"""... $filter ...""",


Все вместе:

SQL(
  s"""
    SELECT name, email, ...
    FROM mailinglistperson
    WHERE $filter LIKE {searchString}
  """).on(
      'searchString -> "%" + searchString + "%"
  ).as(databaseResultParser.*)

но это должно сопровождаться проверкой, что-то вроде

val validColumns = List("name", "email")
if (validColumns.contains(filter)) == false) {
  throw new IllegalArgumentException("...")
}

для защиты от SQL-инъекций.


Обновить

Как указывает cchantep: если используется Anorm> = 2.4, можно использовать смешанную интерполяцию (как для имен столбцов, так и для значений):

SQL"... WHERE #$filter LIKE $searchString"

В этом случае он частично безопасен от внедрения SQL: он охватывает только значения, а не имя столбца.

Обновление 2

Что касается регистрации операторов SQL, см. Где найти зарегистрированные операторы SQL в play2?

Но поскольку вы используете PostgreSQL, я предлагаю точный источник: Журнал PostgreSQL: В postgresql.conf:

log_statement = 'все' # нет, ддл, мод, все

тогда вы увидите в файле журнала PostgreSQL что-то вроде этого:

LOG: выберите * из test50, где имя, как $1

ДЕТАЛИ: Параметр: $1 = '%aaa'

Другие вопросы по тегам