【问题标题】:Perl+Postgresql: a function does not return a value if RAISE NOTICE is presentPerl+Postgresql:如果存在 RAISE NOTICE,函数不返回值
【发布时间】:2009-05-13 17:42:18
【问题描述】:

我注意到,当我使用 DBI 从 Perl 脚本调用 PL/PgSQL 或 PL/Perl 函数时,如果函数中使用了 RAISE NOTICE 或 elog(NOTICE),它不会返回值。举例说明:

一个简单的表格:

CREATE TABLE "public"."table1" (
  "fld" INTEGER
) WITHOUT OIDS;

一个简单的函数:

CREATE OR REPLACE FUNCTION "public"."function1" () RETURNS integer AS
$body$
DECLARE
  myvar INTEGER;
BEGIN
  SELECT INTO myvar fld FROM table1 LIMIT 1;
  RETURN myvar;
END;
$body$
LANGUAGE 'plpgsql'

一段 Perl 脚本:

use DBI;
...
my $ref = $dbh->selectcol_arrayref('SELECT function1()');
print $$ref[0];

按原样打印表格中的值。

但是,如果我按如下方式添加 RAISE NOTICE,则不会得到任何结果:

SELECT INTO myvar fld FROM table1 LIMIT 1;
RAISE NOTICE 'Testing';
RETURN myvar;

我是否遗漏了什么或这种行为是设计使然?

【问题讨论】:

    标签: perl postgresql dbi


    【解决方案1】:

    检查数据库服务器的postgresql.conf 文件中的client_min_messages 设置。来自 PostgreSQL 8.3 文档:

    client_min_messages(字符串)

    控制发送到客户端的消息级别。有效值为DEBUG5DEBUG4DEBUG3DEBUG2DEBUG1LOGNOTICEWARNINGERRORFATAL 和 PANIC。每个级别包括其后的所有级别。级别越高,发送的消息就越少。默认值为NOTICE。请注意,LOG 在此处的排名与在 log_min_messages 中的排名不同。

    【讨论】:

      【解决方案2】:

      使用 Debian 的 Perl 5.10、DBI 1.605 和 DBD::Pg 2.8.7 与 PostgreSQL 8.3.7 相比,我无法重现这一点。我按预期打印了通知。

      steve@steve@[local] =# create or replace function public.function1() returns integer language 'plpgsql' as $$ declare myvar integer; begin select into myvar fld from table1 limit 1; raise notice 'Testing'; return myvar; end; $$;
      CREATE FUNCTION
      steve@steve@[local] =#
      [1]+  Stopped                 psql --cluster 8.3/steve
      steve@arise:~$ DBI_TRACE=1 perl -MData::Dumper -MDBI -e '$dbh = DBI->connect(qw|dbi:Pg:dbname=steve;port=5433;host=/tmp steve steve|, {RaiseError=>1,PrintError=>0}); print Data::Dumper->new([$dbh->selectcol_arrayref("SELECT function1()")], [qw|result|])->Dump'
          DBI 1.605-ithread default trace level set to 0x0/1 (pid 5739) at DBI.pm line 273 via -e line 0
          Note: perl is running without the recommended perl -w option
          -> DBI->connect(dbi:Pg:dbname=steve;port=5433;host=/tmp, steve, ****, HASH(0x1c9ddf0))
          -> DBI->install_driver(Pg) for linux perl=5.010000 pid=5739 ruid=1000 euid=1000
             install_driver: DBD::Pg version 2.8.7 loaded from /usr/lib/perl5/DBD/Pg.pm
          <- install_driver= DBI::dr=HASH(0x1e06a68)
          !! warn: 0 CLEARED by call to connect method
          <- connect('dbname=steve;port=5433;host=/tmp', 'steve', ...)= DBI::db=HASH(0x1fd8e08) at DBI.pm line 638
          <- STORE('RaiseError', 1)= 1 at DBI.pm line 690
          <- STORE('PrintError', 0)= 1 at DBI.pm line 690
          <- STORE('AutoCommit', 1)= 1 at DBI.pm line 690
          <- STORE('Username', 'steve')= 1 at DBI.pm line 693
          <> FETCH('Username')= 'steve' ('Username' from cache) at DBI.pm line 693
          <- connected('dbi:Pg:dbname=steve;port=5433;host=/tmp', 'steve', ...)= undef at DBI.pm line 699
          <- connect= DBI::db=HASH(0x1fd8e08)
          <- STORE('dbi_connect_closure', CODE(0x1da2280))= 1 at DBI.pm line 708
      NOTICE:  Testing
          <- selectcol_arrayref('SELECT function1()')= ( [ '2' ] ) [1 items] at -e line 1
      $result = [
                  '2'
                ];
      

      我建议将您的问题隔离到一个小脚本(如上)并使用DBI_TRACE 运行它,并将其设置为相当高的任何值,看看您看到了什么差异。也许还可以查看 DBD::Pg 的发行说明,看看他们是否提到过它可能在过去被这些混淆了。 DBI_TRACE=10 我看到了这个:

      PQexec
      Begin pg_warn (message: NOTICE:  Testing
       DBIc_WARN: 1 PrintWarn: 1)
      NOTICE:  Testing
      End pg_warn
      Begin _sqlstate
      

      所以你应该在自己的输出中寻找类似的东西。

      【讨论】:

      • 我忘了提到我使用 DBD::PgPP 因为 postgres 在另一个盒子上运行。尝试添加 DBI->trace(),但我仍然看不到结果或通知。在 postgresql.conf 中设置 client_min_messages=error 实际上有帮助。
      • 嗯,听起来 DBD::PgPP 驱动程序无法处理该消息,因此您正在解决该问题。您也可以使用 DBD::Pg 与另一台机器上的 postgres 对话——您只需要安装 libpq 即可使用 DBD::Pg,而不是整个服务器构建。
      • 是的,使用 DBD::PgPP 0.06 会重现问题:建议您向维护者报告。
      • 毕竟,无论如何我都必须安装 DBD::Pg,因为 PgPP 在处理大型查询 (>300K) 时会产生段错误。看看它是如何处理通知的。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      • 2020-04-21
      • 1970-01-01
      • 2015-03-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多