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

Posted

技术标签:

【中文标题】如何使用 Play 框架中的演变在 PostgreSQL 中创建函数?【英文标题】:How do I create a function in PostgreSQL using evolutions in the Play framework? 【发布时间】:2013-03-06 00:27:13 【问题描述】:

使用 Play Framework 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 完全插入到播放框架之外。示例在这里:http://elijah.zupancic.name/files/PgCreateFunction.tar.gz

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

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

【问题讨论】:

您看到的是 Pg 的调试输出,显示了参数化查询及其参数。每个参数都通过 fe/be 协议单独发送,客户端不需要转义。您在此处看到的问题几乎可以肯定只是 Pg 无条件地使用 '' 对参数进行调试表示;实际的参数会很好。如果它未能逃脱,你会看到一个大的 SQL 查询,其中所有参数都被替换了。 您似乎更有可能在多语句分离期间遇到解析美元引号的 PgJDBC 问题。一个独立的可编译示例会很有帮助。 sscce.org 。如果您在编辑中添加详细信息,请在此处发表评论,以便我收到通知。 嗨 Craig,我已按照您的要求添加了 SSCCE。玩看看。它确实在我可以创建的最简单的播放设置中重现。 我不会说 Play - 我知道 Maven 和 Ant 项目结构,但 Play 使用它自己的。你如何运行它?自述文件只是默认生成的。 安装播放框架。然后输入:play run 【参考方案1】:

这是 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;

【讨论】:

以上是关于如何使用 Play 框架中的演变在 PostgreSQL 中创建函数?的主要内容,如果未能解决你的问题,请参考以下文章

使用 MySQL 不受支持的语法播放框架演变

如何使用Slick和Play在测试中应用手动演变! 2.4

部署为 war 文件时如何运行 Play Framework 演变

如何自动测试 playframework 演变

在 Play 中,我可以根据数据库类型应用不同的进化吗?

如何不查看文件以了解 Play 框架中的更改