php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Request #78621 pgsqlSetNoticeCallback
Submitted: 2019-10-02 05:04 UTC Modified: -
From: guillaume-php at outters dot eu Assigned:
Status: Open Package: PDO PgSQL
PHP Version: 7.3.10 OS: all
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If this is not your bug, you can add a comment by following this link.
If this is your bug, but you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: guillaume-php at outters dot eu
New email:
PHP Version: OS:

 

 [2019-10-02 05:04 UTC] guillaume-php at outters dot eu
Description:
------------
There is currently no way to receive PostgreSQL's notices PHP-side.

A PQsetNoticeProcessor has been defined 15 years ago to the empty function _pdo_pgsql_notice, to prevent libpq's default behaviour (fprintfing to stderr)).

Passing notices to PHP could prove useful, allowing e.g. user-defined RAISE NOTICE in PL/pgSQL long-running code to provide feedback.

A user-space callback would give more control on what to do with the message (compared to the exec-then-fetch method of non-PDO pgsql driver's pg_last_notice)… not the least being the live feedback ability.

Test script:
---------------
function disp($message) { echo trim($message)."\n"; }
$db = new PDO('pgsql:host=localhost;port=5432;dbname=…', '', '');
if(method_exists($db, 'pgsqlSetNoticeCallback'))
    $db->pgsqlSetNoticeCallback('disp');
$db->beginTransaction();
$db->exec("create temporary table t (a varchar(3))");
$db->exec("create function hey() returns trigger as \$\$ begin new.a := 'oh'; raise notice 'I tampered your data, did you know?'; return new; end; \$\$ language plpgsql");
$db->exec("create trigger hop before insert on t for each row execute procedure hey()");
$db->exec("insert into t values ('ah')");
print_r($db->query("select * from t")->fetchAll());

Expected result:
----------------
I would like to know that a trigger triggered ("I tampered your data, did you know?").

Actual result:
--------------
Only tcpdump will display my carefully-crafted RAISE NOTICE. 

Patches

pgsqlSetNoticeCallback.7.diff (last revision 2019-10-02 05:05 UTC by guillaume-php at outters dot eu)

Add a Patch

Pull Requests

Pull requests:

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-10-02 05:05 UTC] guillaume-php at outters dot eu
The following patch has been added/updated:

Patch Name: pgsqlSetNoticeCallback.7.diff
Revision:   1569992718
URL:        https://bugs.php.net/patch-display.php?bug=78621&patch=pgsqlSetNoticeCallback.7.diff&revision=1569992718
 [2019-10-13 23:17 UTC] guillaume-php at outters dot eu
The following pull request has been associated:

Patch Name: pgsqlSetNoticeCallback
On GitHub:  https://github.com/php/php-src/pull/4823
Patch:      https://github.com/php/php-src/pull/4823.patch
 [2019-12-04 06:21 UTC] guillaume-php at outters dot eu
Note: I considered adding the PDO itself as a first parameter to the callback.

I don't see a usage for it now *; but who knows… Not me, but I would be open to anyone commenting this point of design: now would be the right time to add a first parameter if you think it could be a good idea (with the usual warnings in the user doc: "you get the parameter, but don't dare doing nasty things with it, you'll be on your own to deal with it").

If no comment, I'll stick with the simple, user-side solution exposed here, that is, to get a calling context, do pass an object method to pgsqlSetNoticeCallback and hold your context in that object.

* Conjecture: someone needing to act on the statement upon receiving a notice, e.g. aborting it?
Objection: wouldn't it raise reentrancy issues? And by the way, what is the "current" statement when we have two, not entirely fetched statements? I'm not even sure we can retrieve it from the notice (the notice being emitted at the connection level, not at the statement level).
Conjecture: use it as a discriminant in the callback to know for which DB we get the notice?
Objection: the callback can be an object method, and the object can hold the calling context.
Conjecture: to be consistent with notice callbacks on other drivers?
Objection: I did not see any other implementation…
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Fri Dec 06 08:01:24 2019 UTC