Skip to content

Commit e735de6

Browse files
committed
Add GC support for PDO driver data
Add a get_gc method that can be implemented by drivers, which can be used to add additional zvals to the GC buffer. Implement GC support for PDO SQLite callbacks in particular. Closes GH-6262.
1 parent d731b76 commit e735de6

File tree

10 files changed

+75
-10
lines changed

10 files changed

+75
-10
lines changed

ext/pdo/pdo_dbh.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1291,8 +1291,12 @@ static int dbh_compare(zval *object1, zval *object2)
12911291
static HashTable *dbh_get_gc(zend_object *object, zval **gc_data, int *gc_count)
12921292
{
12931293
pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(object);
1294-
*gc_data = &dbh->def_stmt_ctor_args;
1295-
*gc_count = 1;
1294+
zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create();
1295+
zend_get_gc_buffer_add_zval(gc_buffer, &dbh->def_stmt_ctor_args);
1296+
if (dbh->methods->get_gc) {
1297+
dbh->methods->get_gc(dbh, gc_buffer);
1298+
}
1299+
zend_get_gc_buffer_use(gc_buffer, gc_data, gc_count);
12961300
return zend_std_get_properties(object);
12971301
}
12981302

ext/pdo/php_pdo_driver.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,10 @@ typedef int (*pdo_dbh_check_liveness_func)(pdo_dbh_t *dbh);
286286
* scope */
287287
typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh);
288288

289+
/* Called when the PDO handle is scanned for GC. Should populate the get_gc buffer
290+
* with any zvals in the driver_data that would be freed if the handle is destroyed. */
291+
typedef void (*pdo_dbh_get_gc_func)(pdo_dbh_t *dbh, zend_get_gc_buffer *buffer);
292+
289293
/* for adding methods to the dbh or stmt objects
290294
pointer to a list of driver specific functions. The convention is
291295
to prefix the function names using the PDO driver name; this will
@@ -316,6 +320,7 @@ struct pdo_dbh_methods {
316320
pdo_dbh_get_driver_methods_func get_driver_methods;
317321
pdo_dbh_request_shutdown persistent_shutdown;
318322
pdo_dbh_txn_func in_transaction;
323+
pdo_dbh_get_gc_func get_gc;
319324
};
320325

321326
/* }}} */

ext/pdo_dblib/dblib_driver.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,8 @@ static const struct pdo_dbh_methods dblib_methods = {
417417
NULL, /* check liveness */
418418
NULL, /* get driver methods */
419419
NULL, /* request shutdown */
420-
NULL /* in transaction */
420+
NULL, /* in transaction */
421+
NULL /* get gc */
421422
};
422423

423424
static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)

ext/pdo_firebird/firebird_driver.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1005,7 +1005,11 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */
10051005
NULL, /* last_id not supported */
10061006
pdo_firebird_fetch_error_func,
10071007
firebird_handle_get_attribute,
1008-
NULL /* check_liveness */
1008+
NULL, /* check_liveness */
1009+
NULL, /* get driver methods */
1010+
NULL, /* request shutdown */
1011+
NULL, /* in transaction */
1012+
NULL /* get gc */
10091013
};
10101014
/* }}} */
10111015

ext/pdo_mysql/mysql_driver.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -563,7 +563,8 @@ static const struct pdo_dbh_methods mysql_methods = {
563563
pdo_mysql_check_liveness,
564564
NULL,
565565
pdo_mysql_request_shutdown,
566-
pdo_mysql_in_transaction
566+
pdo_mysql_in_transaction,
567+
NULL /* get_gc */
567568
};
568569
/* }}} */
569570

ext/pdo_oci/oci_driver.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -705,9 +705,10 @@ static const struct pdo_dbh_methods oci_methods = {
705705
pdo_oci_fetch_error_func,
706706
oci_handle_get_attribute,
707707
pdo_oci_check_liveness, /* check_liveness */
708-
NULL, /* get_driver_methods */
709-
NULL,
710-
NULL
708+
NULL, /* get_driver_methods */
709+
NULL, /* request_shutdown */
710+
NULL, /* in_transaction */
711+
NULL /* get_gc */
711712
};
712713

713714
static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */

ext/pdo_odbc/odbc_driver.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,11 @@ static const struct pdo_dbh_methods odbc_methods = {
384384
NULL, /* last id */
385385
pdo_odbc_fetch_error_func,
386386
odbc_handle_get_attr, /* get attr */
387-
NULL, /* check_liveness */
387+
NULL, /* check_liveness */
388+
NULL, /* get_driver_methods */
389+
NULL, /* request_shutdown */
390+
NULL, /* in_transaction */
391+
NULL /* get_gc */
388392
};
389393

390394
static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */

ext/pdo_pgsql/pgsql_driver.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1179,6 +1179,7 @@ static const struct pdo_dbh_methods pgsql_methods = {
11791179
pdo_pgsql_get_driver_methods, /* get_driver_methods */
11801180
NULL,
11811181
pgsql_handle_in_transaction,
1182+
NULL /* get_gc */
11821183
};
11831184

11841185
static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */

ext/pdo_sqlite/sqlite_driver.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -695,6 +695,25 @@ static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh)
695695
}
696696
}
697697

698+
static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer)
699+
{
700+
pdo_sqlite_db_handle *H = dbh->driver_data;
701+
702+
struct pdo_sqlite_func *func = H->funcs;
703+
while (func) {
704+
zend_get_gc_buffer_add_zval(gc_buffer, &func->func);
705+
zend_get_gc_buffer_add_zval(gc_buffer, &func->step);
706+
zend_get_gc_buffer_add_zval(gc_buffer, &func->fini);
707+
func = func->next;
708+
}
709+
710+
struct pdo_sqlite_collation *collation = H->collations;
711+
while (collation) {
712+
zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback);
713+
collation = collation->next;
714+
}
715+
}
716+
698717
static const struct pdo_dbh_methods sqlite_methods = {
699718
sqlite_handle_closer,
700719
sqlite_handle_preparer,
@@ -710,7 +729,8 @@ static const struct pdo_dbh_methods sqlite_methods = {
710729
NULL, /* check_liveness: not needed */
711730
get_driver_methods,
712731
pdo_sqlite_request_shutdown,
713-
NULL
732+
NULL, /* in_transaction */
733+
pdo_sqlite_get_gc
714734
};
715735

716736
static char *make_filename_safe(const char *filename)

ext/pdo_sqlite/tests/gc.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
GC support for PDO Sqlite driver data
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo_sqlite')) print 'skip not loaded';
6+
?>
7+
--FILE--
8+
<?php
9+
10+
class Obj {
11+
public $a;
12+
public function callback() { }
13+
}
14+
15+
$obj = new Obj;
16+
$obj->a = new PDO('sqlite::memory:');
17+
$obj->a->sqliteCreateFunction('func1', function() use ($obj) {}, 1);
18+
$obj->a->sqliteCreateAggregate('func2', function() use ($obj) {}, function() use($obj) {});
19+
$obj->a->sqliteCreateCollation('col', function() use ($obj) {});
20+
21+
?>
22+
===DONE===
23+
--EXPECT--
24+
===DONE===

0 commit comments

Comments
 (0)