Groovy sql.rows返回org.postgresql.util.PSQLException:未安装hstore扩展。

6

我正在使用Groovy Sql在Grails中使用命名参数从Postgres DB获取结果。我的语句是动态生成的,即被连接起来成为最终语句,并且在我进行操作时将参数添加到映射中。

sqlWhere += " AND bar = :namedParam1"
paramsMap.namedParam1 = "blah"

为了更好的可读性,我使用groovy字符串语法,使我可以将SQL语句分成多行编写,如下所示:

sql = """
      SELECT *
      FROM foo
      WHERE 1=1
      ${sqlWhere}
      """

表达式被计算为包含换行符 \n 的字符串:
SELECT *\n ...

当我像这样传递参数时,这不是一个问题。

results = sql.rows(sqlString, paramsMap)

但是如果paramsMap为空(这种情况发生了,因为AND bar = :namedParam1并不总是被连接到查询中)它就会变成一个错误。我会收到一个错误提示。

org.postgresql.util.PSQLException: No hstore extension installed  

这似乎并不真正涉及问题的本质。目前我已经通过if...else解决了这个问题。

if (sqlQuery.params.size() > 0) {
    results = sql.rows(sqlString, paramsMap)
} else {
    results = sql.rows(sqlString.replace('\n',' '))
}

但这似乎有点奇怪(特别是如果我在if分支中也使用replace,它就不起作用)。

我的问题是:为什么我真的会收到这个错误消息,是否有更好的方法来防止它发生?


我的猜测是,你的 sqlStringsql?或者你周围有一些 def sqlString = sql.toString() 的代码吗?如果你将一个 GString 传递给 Groovy SQL,它会为你引用 ${...},最终导致错误的 SQL。 - cfrick
检查运行 SQL 是否有帮助 - CREATE EXTENSION hstore; - Rao
嗨@cfrick,我有一个声明为def String sqlString的声明,但它在途中变成了GString。我现在在传递给sql.rows之前添加了toString(),但错误仍然存在。 - Roland
嗨@Rao,由于我没有使用hstore可以提供的任何内容,我想要避免使用它,尽管如果没有其他解释我的问题,我可能会尝试使用它,只是为了可能获得更好的错误消息。 - Roland
记录发送到数据库的有效语句(由于错误可能已经记录),并查看最终在数据库中的结果。很有可能是某些虚假引用导致的问题。通常查看生成的SQL语句就可以很明显地发现问题所在。 - cfrick
@cfrick:谢谢,这可能是个好主意,不过我得检查一下我们是否已经启用了它(如果没有的话就要启用)。这需要一些时间。 - Roland
1个回答

3

这显然是groovy.sql.SQL实现中的一个bug。方法rows()不能处理作为params传递的空map。作为解决方法,您可以测试它并传递一个空的list

def paramsMap = [:]
...
if (paramsMap.isEmpty())
    paramsMap= []

问题创建于https://issues.apache.org/jira/browse/GROOVY-8082


2
GROOVY-8082问题现已解决。下一个版本2.4.9预计在一两周内发布。现在,您可以指定一个空映射,以替换不需要替换占位符值的情况。 - Paul King

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接