Skip to content

Commit a9259c0

Browse files
authored
Add Pdo\Pgsql::setNoticeCallback() (#14299)
This moves the new method from magically being added to the PDO class from the driver to just be available on the dedicated subclass. Drive-by fixes to NEWS and UPGRADING
1 parent 25579a8 commit a9259c0

16 files changed

+221
-51
lines changed

NEWS

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -170,32 +170,32 @@ PHP NEWS
170170

171171
- PDO_DBLIB:
172172
. Fixed setAttribute and getAttribute. (SakiTakamachi)
173-
. Added class PdoDbLib. (danack, kocsismate)
173+
. Added class Pdo\DbLib. (danack, kocsismate)
174174

175175
- PDO_FIREBIRD:
176176
. Fixed setAttribute and getAttribute. (SakiTakamachi)
177177
. Feature: Add transaction isolation level and mode settings to pdo_firebird.
178178
(SakiTakamachi)
179-
. Added class PdoFirebird. (danack, kocsismate)
179+
. Added class Pdo\Firebird. (danack, kocsismate)
180180

181181
- PDO_MYSQL:
182182
. Fixed setAttribute and getAttribute. (SakiTakamachi)
183-
. Added class PdoMysql. (danack, kocsismate)
183+
. Added class Pdo\Mysql. (danack, kocsismate)
184184

185185
- PDO_ODBC:
186-
. Added class PdoOdbc. (danack, kocsismate)
186+
. Added class Pdo\Odbc. (danack, kocsismate)
187187

188188
- PDO_PGSQL:
189189
. Fixed GH-12423, DSN credentials being prioritized over the user/password
190190
PDO constructor arguments. (SakiTakamachi)
191191
. Fixed native float support with pdo_pgsql query results. (Yurunsoft)
192-
. Added class PdoPgsql. (danack, kocsismate)
192+
. Added class Pdo\Pgsql. (danack, kocsismate)
193193
. Retrieve the memory usage of the query result resource. (KentarouTakeda)
194-
. Added PDO::pgsqlSetNoticeCallBack method to receive DB notices.
194+
. Added Pdo\Pgsql::setNoticeCallBack method to receive DB notices.
195195
(outtersg)
196196

197197
- PDO_SQLITE:
198-
. Added class PdoSqlite. (danack, kocsismate)
198+
. Added class Pdo\Sqlite. (danack, kocsismate)
199199
. Fixed bug #81227 (PDO::inTransaction reports false when in transaction).
200200
(nielsdos)
201201

UPGRADING

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -263,22 +263,22 @@ PHP 8.4 UPGRADE NOTES
263263
or by invoking their constructor directly.
264264

265265
- PDO_DBLIB:
266-
. Added class PdoDbLib.
266+
. Added class Pdo\DbLib.
267267

268268
- PDO_FIREBIRD:
269-
. Added class PdoFirebird.
269+
. Added class Pdo\Firebird.
270270

271271
- PDO_MYSQL:
272-
. Added class PdoMysql.
272+
. Added class Pdo\Mysql.
273273

274274
- PDO_ODBC:
275-
. Added class PdoOdbc.
275+
. Added class Pdo\Odbc.
276276

277277
- PDO_PGSQL:
278-
. Added class PdoPgsql.
278+
. Added class Pdo\Pgsql.
279279

280280
- PDO_SQLITE:
281-
. Added class PdoSqlite.
281+
. Added class Pdo\Sqlite.
282282

283283
- POSIX:
284284
. Added constant POSIX_SC_CHILD_MAX
@@ -546,7 +546,7 @@ PHP 8.4 UPGRADE NOTES
546546
energy consumption) of the current process and pcntl_setqos_class to set it.
547547

548548
- PDO_PGSQL:
549-
. Added PDO::pgsqlSetNoticeCallback to allow a callback to be triggered on
549+
. Added Pdo\Pgsql::setNoticeCallback() to allow a callback to be triggered on
550550
every notice sent (e.g. RAISE NOTICE).
551551

552552
- PGSQL:

ext/pdo/php_pdo.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,24 @@ PHP_MINFO_FUNCTION(pdo);
5555

5656
#define LONG_CONST(c) (zend_long) c
5757

58+
#define PDO_CONSTRUCT_CHECK_COND dbh->driver
59+
#define PDO_CONSTRUCT_CHECK_FAIL() \
60+
{ \
61+
zend_throw_error(NULL, "%s object is uninitialized", ZSTR_VAL(Z_OBJ(EX(This))->ce->name)); \
62+
} \
63+
5864
#define PDO_CONSTRUCT_CHECK \
59-
if (!dbh->driver) { \
60-
zend_throw_error(NULL, "%s object is uninitialized", ZSTR_VAL(Z_OBJ(EX(This))->ce->name)); \
65+
if (!(PDO_CONSTRUCT_CHECK_COND)) { \
66+
PDO_CONSTRUCT_CHECK_FAIL(); \
6167
RETURN_THROWS(); \
6268
} \
6369

6470

71+
#define PDO_CONSTRUCT_CHECK_WITH_CLEANUP(cleanup) \
72+
if (!(PDO_CONSTRUCT_CHECK_COND)) { \
73+
PDO_CONSTRUCT_CHECK_FAIL(); \
74+
goto cleanup; \
75+
} \
76+
77+
6578
#endif /* PHP_PDO_H */

ext/pdo_pgsql/pdo_pgsql.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,36 @@ PHP_METHOD(Pdo_Pgsql, getPid)
145145
pgsqlGetPid_internal(INTERNAL_FUNCTION_PARAM_PASSTHRU);
146146
}
147147

148+
/* Sets a callback to receive DB notices (after client_min_messages has been set */
149+
PHP_METHOD(Pdo_Pgsql, setNoticeCallback)
150+
{
151+
zend_fcall_info fci = empty_fcall_info;
152+
zend_fcall_info_cache fcc = empty_fcall_info_cache;
153+
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS(), "F!", &fci, &fcc)) {
154+
RETURN_THROWS();
155+
}
156+
157+
pdo_dbh_t *dbh = Z_PDO_DBH_P(ZEND_THIS);
158+
PDO_CONSTRUCT_CHECK_WITH_CLEANUP(cleanup);
159+
160+
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
161+
162+
pdo_pgsql_cleanup_notice_callback(H);
163+
164+
if (ZEND_FCC_INITIALIZED(fcc)) {
165+
H->notice_callback = emalloc(sizeof(zend_fcall_info_cache));
166+
zend_fcc_dup(H->notice_callback, &fcc);
167+
}
168+
169+
return;
170+
171+
cleanup:
172+
if (ZEND_FCC_INITIALIZED(fcc)) {
173+
zend_fcc_dtor(&fcc);
174+
}
175+
RETURN_THROWS();
176+
}
177+
148178
/* true global environment */
149179

150180
/* {{{ PHP_MINIT_FUNCTION */

ext/pdo_pgsql/pdo_pgsql.stub.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,6 @@ public function lobUnlink(string $oid): bool {}
5656
public function getNotify(int $fetchMode = \PDO::FETCH_DEFAULT, int $timeoutMilliseconds = 0): array|false {}
5757

5858
public function getPid(): int {}
59+
60+
public function setNoticeCallback(?callable $callback): void {}
5961
}

ext/pdo_pgsql/pdo_pgsql_arginfo.h

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/pdo_pgsql/pgsql_driver.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ static void pdo_pgsql_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *i
131131
}
132132
/* }}} */
133133

134-
static void pdo_pgsql_cleanup_notice_callback(pdo_pgsql_db_handle *H) /* {{{ */
134+
void pdo_pgsql_cleanup_notice_callback(pdo_pgsql_db_handle *H) /* {{{ */
135135
{
136136
if (H->notice_callback) {
137137
zend_fcc_dtor(H->notice_callback);
@@ -1241,8 +1241,7 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlGetPid)
12411241
}
12421242
/* }}} */
12431243

1244-
/* {{{ proto void PDO::pgsqlSetNoticeCallback(mixed callback)
1245-
Sets a callback to receive DB notices (after client_min_messages has been set) */
1244+
/* {{{ Sets a callback to receive DB notices (after client_min_messages has been set) */
12461245
PHP_METHOD(PDO_PGSql_Ext, pgsqlSetNoticeCallback)
12471246
{
12481247
zend_fcall_info fci = empty_fcall_info;
@@ -1252,7 +1251,7 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlSetNoticeCallback)
12521251
}
12531252

12541253
pdo_dbh_t *dbh = Z_PDO_DBH_P(ZEND_THIS);
1255-
PDO_CONSTRUCT_CHECK;
1254+
PDO_CONSTRUCT_CHECK_WITH_CLEANUP(cleanup);
12561255

12571256
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
12581257

@@ -1262,6 +1261,14 @@ PHP_METHOD(PDO_PGSql_Ext, pgsqlSetNoticeCallback)
12621261
H->notice_callback = emalloc(sizeof(zend_fcall_info_cache));
12631262
zend_fcc_dup(H->notice_callback, &fcc);
12641263
}
1264+
1265+
return;
1266+
1267+
cleanup:
1268+
if (ZEND_FCC_INITIALIZED(fcc)) {
1269+
zend_fcc_dtor(&fcc);
1270+
}
1271+
RETURN_THROWS();
12651272
}
12661273
/* }}} */
12671274

ext/pdo_pgsql/pgsql_driver.stub.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ public function pgsqlGetNotify(int $fetchMode = PDO::FETCH_DEFAULT, int $timeout
3434
/** @tentative-return-type */
3535
public function pgsqlGetPid(): int {}
3636

37-
/** @tentative-return-type */
38-
public function pgsqlSetNoticeCallback(?callable $callback): void {}
37+
/* Do NOT add new methods here. See https://wiki.php.net/rfc/pdo_driver_specific_subclasses
38+
* Any new feature should be declared only on Pdo\Pgsql.
39+
*/
3940
}

ext/pdo_pgsql/pgsql_driver_arginfo.h

Lines changed: 1 addition & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ext/pdo_pgsql/php_pdo_pgsql_int.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ enum pdo_pgsql_specific_constants {
108108
php_stream *pdo_pgsql_create_lob_stream(zval *pdh, int lfd, Oid oid);
109109
extern const php_stream_ops pdo_pgsql_lob_stream_ops;
110110

111+
void pdo_pgsql_cleanup_notice_callback(pdo_pgsql_db_handle *H);
112+
111113
void pdo_libpq_version(char *buf, size_t len);
112114
void pdo_pgsql_close_lob_streams(pdo_dbh_t *dbh);
113115

ext/pdo_pgsql/tests/issue78621.inc

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
11
<?php
22
require_once dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
33
require_once dirname(__FILE__) . '/config.inc';
4-
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
4+
if (!isset($db)) {
5+
$db = new Pdo\Pgsql($config['ENV']['PDOTEST_DSN']);
6+
}
7+
if (!isset($rounds) || empty($rounds)) {
8+
$rounds = [ null, 'Re' ];
9+
}
510

6-
attach($db);
11+
attach($db, array_shift($rounds));
712

813
$db->beginTransaction();
914
$db->exec("set client_min_messages to notice");
1015
$db->exec("create temporary table t (a varchar(3))");
1116
$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");
1217
$db->exec("create trigger hop before insert on t for each row execute procedure hey()");
1318
$db->exec("insert into t values ('ah')");
14-
attach($db, 'Re');
15-
$db->exec("delete from t");
16-
$db->exec("insert into t values ('ah')");
17-
$db->pgsqlSetNoticeCallback(null);
19+
while (count($rounds)) {
20+
try {
21+
attach($db, array_shift($rounds));
22+
} catch (Throwable $err) {
23+
echo "Caught ".get_class($err).": ".$err->getMessage()."\n";
24+
}
25+
try {
26+
$db->exec("delete from t");
27+
$db->exec("insert into t values ('ah')");
28+
} catch (Throwable $err) {
29+
echo "Caught ".get_class($err)." ".$err->getMessage()."\n";
30+
}
31+
}
32+
$db->setNoticeCallback(null);
1833
$db->exec("delete from t");
1934
$db->exec("insert into t values ('ah')");
2035
var_dump($db->query("select * from t")->fetchAll(PDO::FETCH_ASSOC));

ext/pdo_pgsql/tests/issue78621.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
pgsqlSetNoticeCallback catches Postgres "raise notice".
2+
Pdo\Pgsql::setNoticeCallback catches Postgres "raise notice".
33
--SKIPIF--
44
<?php
55
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
@@ -13,7 +13,7 @@ function disp($message) { echo trim($message)."\n"; }
1313
function dispRe($message) { echo "Re".trim($message)."\n"; }
1414
function attach($db, $prefix = '')
1515
{
16-
$db->pgsqlSetNoticeCallback('disp'.$prefix);
16+
$db->setNoticeCallback('disp'.$prefix);
1717
}
1818
require dirname(__FILE__) . '/issue78621.inc';
1919
?>

ext/pdo_pgsql/tests/issue78621_closure.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
pgsqlSetNoticeCallback catches Postgres "raise notice".
2+
Pdo\Pgsql::setNoticeCallback catches Postgres "raise notice".
33
--SKIPIF--
44
<?php
55
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
@@ -16,13 +16,13 @@ function attach($db, $prefix = '')
1616
switch($flavor)
1717
{
1818
case 0:
19-
$db->pgsqlSetNoticeCallback(function($message) use($prefix) { echo $prefix.trim($message)."\n"; });
19+
$db->setNoticeCallback(function($message) use($prefix) { echo $prefix.trim($message)."\n"; });
2020
// https://github.com/php/php-src/pull/4823#pullrequestreview-335623806
2121
$eraseCallbackMemoryHere = (object)[1];
2222
break;
2323
case 1:
2424
$closure = function($message) use($prefix) { echo $prefix.'('.get_class($this).')'.trim($message)."\n"; };
25-
$db->pgsqlSetNoticeCallback($closure->bindTo(new \stdClass));
25+
$db->setNoticeCallback($closure->bindTo(new \stdClass));
2626
break;
2727
}
2828
}

0 commit comments

Comments
 (0)