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'