如何使用 Play 框架中的进化在 PostgreSQL 中创建函数?

问题描述 投票:0回答:2

使用 Play 框架 2.1

我在演化中定义了以下 SQL:

CREATE OR REPLACE FUNCTION idx(myArray anyarray, myElement anyelement) RETURNS int AS $$
 SELECT i FROM (
  SELECT generate_series(array_lower(myArray,1),array_upper(myArray,1))
 ) g(i)
 WHERE myArray[i] = anyElement
 LIMIT 1; $$ LANGUAGE sql IMMUTABLE;

当我执行进化时,出现以下错误:

We got the following error: ERROR: unterminated dollar-quoted string at or near 
"$$ SELECT i FROM ( SELECT generate_series(array_lower(myArray,1),
 array_upper(myArray,1)) ) g(i) WHERE myArray[i] = anyElement LIMIT 1" Position:
 87 [ERROR:0, SQLSTATE:42601], while trying to run this SQL script:

我使用的是 PostgreSQL 驱动程序版本 9.1-901.jdbc4。

我查看了 postgres 查询日志,发现 Play 正在尝试执行以下操作:

LOG:  execute <unnamed>: insert into play_evolutions values($1, $2, $3, $4, $5, $6, $7)
PST DETAIL:  parameters: $1 = '1',
                         $2 = 'c834d463ebd9916b0a3388040300a0926514faef',
                         $3 = '2013-03-05 00:00:00',
                         $4 = '-- THE EVOLUTION UP STATEMENTS GO HERE',
                         $5 = '-- THE EVOLUTION DOWN STATEMENTS GO HERE',
                         $6 = 'applying_up',
                         $7 = ''

因此,出于某种原因,Play 尝试将 SQL 插入到文本列中,而没有正确转义。还有其他人找到解决此问题的方法吗?您认为这是 JDBC 问题而不是 Play 问题吗?另外,有人让 Liquibase 与 Play 2.1 一起使用吗?

此外,仅将 $$ 更改为 ' 也不起作用。在这种情况下,我们会得到不同的错误,但我们仍然无法执行进化。

编辑:我添加了一个来自全新游戏项目的示例。请下载:http://elijah.zupancic.name/files/play_evolution_problem.tar.gz

要使示例正常工作,您需要创建一个新数据库,如演化 1.sql 的第一条评论所示。然后你需要配置你的conf/application.conf以使用正确的用户连接到正确的端口上的postgres。

我刚刚做了一个实验,尝试将创建函数sql完全插入到play框架之外。示例在这里:http://elijah.zupancic.name/files/PgCreateFunction.tar.gz<

事实证明它的重现性非常好。

编辑:事实证明我无法用Java重现它。

postgresql jdbc playframework-2.1 postgresql-9.2 playframework-evolutions
2个回答
20
投票

这是 Play 解析进化的一个产物。由于它用分号解析每个语句,因此它无法处理存储过程定义。该问题已在 Play 2.1 中得到解决,允许您通过加倍来指定嵌入的分号。例如,请参阅https://github.com/playframework/Play20/pull/649

使用

;;
为我解决了类似的问题,使用 Play 2.1。我建议你按如下方式重新定义你的进化,然后再试一次:

CREATE OR REPLACE FUNCTION idx(myArray anyarray, myElement anyelement) RETURNS int AS $$
 SELECT i FROM (
  SELECT generate_series(array_lower(myArray,1),array_upper(myArray,1))
 ) g(i)
 WHERE myArray[i] = anyElement
 LIMIT 1;; $$ LANGUAGE sql IMMUTABLE;

0
投票

您可以在退货声明中使用一个美元符号。简单的例子:

CREATE OR REPLACE FUNCTION sys_extract_utc(
    time_in timestamp with time zone)
    RETURNS timestamp without time zone
    LANGUAGE 'sql'
    PARALLEL SAFE
    return $1 at time zone 'UTC';
© www.soinside.com 2019 - 2024. All rights reserved.