Raise notice is typically used to debug PSQL scripts in postgres (link).
The docs say that there's some kind of support for printing notices when using the pg gem, but there's no info on how to use this proc, what it yields, possible (probable?) caveats etc.
Does anyone have a working code example for production and/or development? Ideally, I'm looking for a solution that allows PG notices to be printed out in development when Sequel logging is enabled.
When I do:
DB = Sequel.connect(
ENV['DATABASE_URL'],
notice_receiver: lambda{ |x| binding.pry }
)
the notice_receiver
lambda never gets called once I execute a function that raises a notice. I.e
[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=>""}
where emit notice is:
CREATE OR REPLACE FUNCTION emit_notice()
RETURNS VOID AS $$
BEGIN
RAISE NOTICE 'NOTICE ME!!!';
END;
$$ LANGUAGE plpgsql;
and it works from PgAdmin:
NOTICE: NOTICE ME!!!
Total query runtime: 21 ms.
1 row retrieved.
UPDATE
Alejandro C gave a good working example, and it seems that notices don't get distributed with the notice_receiver
hook. For example:
Sequel.connect(DB.opts.merge(:notice_receiver=>proc{|r| puts r.result_error_message})){ |db|
db.do("BEGIN\nRAISE NOTICE 'foo';\nEND;")
}
prints nothing, and:
Sequel.connect(DB.opts.merge(:notice_receiver=>proc{|r| puts r.result_error_message})){ |db|
db.do("BEGIN\nRAISE WARNING 'foo';\nEND;")
}
Prints
WARNING: foo
Since Sequel just calls set_notice_receiver
from PG, I guess I should file a bug report with PG.
EDIT 2
Yet when I try things just with the PG gem I get
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>
So at this point I'm a bit confused...
EDIT 3
EDIT 4
Ah, apparently there's another options you need to use, client_min_messages
needs to be set to :notice
as so:
DB = Sequel.connect(
ENV['DATABASE_URL'],
notice_receiver: proc{|r| puts r.result_error_message},
client_min_messages: :notice
)
and this works
You pass in your own proc which gets the notice as a string. To have it trigger on notices and not just warnings and above, use client_min_messages. For example:
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