【问题标题】:How to print postgres "raise notice" output from Sequel?如何从 Sequel 打印 postgres“提高通知”输出?
【发布时间】:2017-10-17 02:24:30
【问题描述】:

引发通知通常用于在 postgres (link) 中调试 PSQL 脚本。

The docs say that there's some kind of support for printing notices when using the pg gem,但没有关于如何使用这个过程、它产生什么、可能(可能?)警告等的信息。

是否有人提供用于生产和/或开发的有效代码示例?理想情况下,我正在寻找一种解决方案,允许在启用 Sequel 日志记录时在开发中打印出 PG 通知。

当我这样做时:

DB = Sequel.connect(
  ENV['DATABASE_URL'],
  notice_receiver: lambda{ |x| binding.pry }
)

一旦我执行一个引发通知的函数,notice_receiver lambda 就永远不会被调用。即

[1] pry(#<Psql::CalculateMasterBalancesTest>)> DB.select{ |o| Sequel.function(:emit_notice) }.first
I, [2017-05-17T16:51:56.746003 #23139]  INFO -- : (0.000335s) SELECT emit_notice() LIMIT 1
=> {:emit_notice=>""}

发出通知在哪里:

CREATE OR REPLACE FUNCTION emit_notice()
  RETURNS VOID AS $$

BEGIN
  RAISE NOTICE 'NOTICE ME!!!';
END;
$$ LANGUAGE plpgsql;

它在 PgAdmin 中工作:

NOTICE:  NOTICE ME!!!
Total query runtime: 21 ms.
1 row retrieved.

更新

Alejandro C 给出了一个很好的工作示例,通知似乎没有通过notice_receiver 挂钩分发。例如:

Sequel.connect(DB.opts.merge(:notice_receiver=>proc{|r| puts r.result_error_message})){ |db|
  db.do("BEGIN\nRAISE NOTICE 'foo';\nEND;")
}

什么都不打印,并且:

Sequel.connect(DB.opts.merge(:notice_receiver=>proc{|r| puts r.result_error_message})){ |db|
  db.do("BEGIN\nRAISE WARNING 'foo';\nEND;")
}

打印

警告:foo

既然Sequel just calls set_notice_receiver from PG,我想我应该向PG提交错误报告。

编辑 2

然而,当我尝试使用我得到的 PG gem 时

conn = PG.connect( :dbname => 'db_test', user: 'test', password: 'test', host: '127.0.0.1' )
conn.set_notice_receiver{|r| puts r.result_error_message }
conn.exec("SELECT emit_notice()")
NOTICE:  NOTICE ME!!!
=> #<PG::Result:0x0000000405ac18 status=PGRES_TUPLES_OK ntuples=1 nfields=1 cmd_tuples=1>

所以在这一点上我有点困惑......

编辑 3

Posted an issue GitHub...

编辑 4

啊,显然你需要使用另一个选项,client_min_messages 需要设置为 :notice,这样:

DB = Sequel.connect(
  ENV['DATABASE_URL'],
  notice_receiver: proc{|r| puts r.result_error_message},
  client_min_messages: :notice
)

这行得通

【问题讨论】:

    标签: ruby postgresql sequel


    【解决方案1】:

    你传入你自己的 proc,它以字符串的形式获取通知。要让它在通知而不是just warnings and above 上触发,请使用 client_min_messages。例如:

    a = nil
    Sequel.connect(
      DB.opts.merge(
          notice_receiver: proc{|r| a = r.result_error_message}, 
          client_min_messages: :notice)) { |db|
      db.do("BEGIN\nRAISE WARNING 'foo';\nEND;")
    }
    a == "WARNING:  foo\n" # true
    

    【讨论】:

    • 嗯,谢谢,我会玩的。我用我现在尝试过的一些东西更新了答案
    • DB.inspect 返回 "#&lt;Sequel::Postgres::Database: \"postgres://test:test@127.0.0.1:5432/db_test\" {:notice_receiver=&gt;#&lt;Proc:0x00000003f2e0d8@.../Backend/config/initializers/00_database.rb:4&gt;}&gt;"require 'pg' 返回 false 所以我猜它是正确的适配器?
    • Hmf,我搞定了,通知似乎没有通过 notice_receiver 钩子分发,但警告可以。我现在将通过使用 raise warning 来解决这个问题,我应该在哪里做 raise notice 并查看源代码发生了什么。
    • 尝试在规范中将 client_min_messages 设置为 :notice
    • 想要编辑您的答案以包含client_min_messages 角度,我会接受吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-03
    • 1970-01-01
    • 1970-01-01
    • 2019-11-18
    • 1970-01-01
    • 1970-01-01
    • 2013-11-21
    相关资源
    最近更新 更多