Anorm 返回 0 个结果,而 psql returns 2 个结果
Anorm returning 0 results while psql returns 2 results
我通过 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, Whosebug, twitter, blog
FROM mailinglistperson
WHERE {filter} LIKE '%{searchString}%'
""").on(
'filter -> filter,
'searchString -> searchString
).as(databaseResultParser.*)
}
}
当我 运行 使用与上述异常代码同构的 psql
对数据库 (PostgreSQL) 进行查询时,它 returns 2 结果,即:
select id, name, email from mailinglistperson where company like '%kixer%';
但是当传递完全相同的值时异常代码 returns 0 结果(我已经通过 println 验证了这些值)
编辑:当我将异常代码切换为使用字符串插值时,我得到:
[error] - play.core.server.netty.PlayDefaultUpstreamHandler - Cannot invoke the action
java.lang.RuntimeException: No parameter value for placeholder: 3
EDIT2:我还尝试将“%...%”与 searchString 一起传递到 LIKE 中,但仍然得到 0 个结果。
有两个问题 - 列名和过滤器值
至于过滤器值:您必须在SQL命令中省略单刻度,并且您应该在参数中传递占位符“%”。如果是字符串,则会自动处理刻度。
至于列名称:它就像一个字符串参数,所以报价也会自动处理:
[debug] c.j.b.PreparedStatementHandle - select ... from ... where 'filter' like '%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 语句,请参阅 Where to see the logged sql statements in play2?
但是当您使用 PostgreSQL 时,我建议使用权威来源:PostgreSQL 日志:在 postgresql.conf
:
log_statement = 'all' # none, ddl, mod, all
然后您将在 PostgreSQL 日志文件中看到如下内容:
LOG: select * from test50 where name like
DETAIL: Parameter: = '%aaa'
我通过 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, Whosebug, twitter, blog
FROM mailinglistperson
WHERE {filter} LIKE '%{searchString}%'
""").on(
'filter -> filter,
'searchString -> searchString
).as(databaseResultParser.*)
}
}
当我 运行 使用与上述异常代码同构的 psql
对数据库 (PostgreSQL) 进行查询时,它 returns 2 结果,即:
select id, name, email from mailinglistperson where company like '%kixer%';
但是当传递完全相同的值时异常代码 returns 0 结果(我已经通过 println 验证了这些值)
编辑:当我将异常代码切换为使用字符串插值时,我得到:
[error] - play.core.server.netty.PlayDefaultUpstreamHandler - Cannot invoke the action
java.lang.RuntimeException: No parameter value for placeholder: 3
EDIT2:我还尝试将“%...%”与 searchString 一起传递到 LIKE 中,但仍然得到 0 个结果。
有两个问题 - 列名和过滤器值
至于过滤器值:您必须在SQL命令中省略单刻度,并且您应该在参数中传递占位符“%”。如果是字符串,则会自动处理刻度。
至于列名称:它就像一个字符串参数,所以报价也会自动处理:
[debug] c.j.b.PreparedStatementHandle - select ... from ... where 'filter' like '%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 语句,请参阅 Where to see the logged sql statements in play2?
但是当您使用 PostgreSQL 时,我建议使用权威来源:PostgreSQL 日志:在 postgresql.conf
:
log_statement = 'all' # none, ddl, mod, all
然后您将在 PostgreSQL 日志文件中看到如下内容:
LOG: select * from test50 where name like
DETAIL: Parameter: = '%aaa'