diff options
-rw-r--r-- | ext/pdo/pdo_dbh.c | 8 | ||||
-rw-r--r-- | ext/pdo/php_pdo_driver.h | 5 | ||||
-rw-r--r-- | ext/pdo_dblib/dblib_driver.c | 3 | ||||
-rw-r--r-- | ext/pdo_firebird/firebird_driver.c | 6 | ||||
-rw-r--r-- | ext/pdo_mysql/mysql_driver.c | 3 | ||||
-rw-r--r-- | ext/pdo_oci/oci_driver.c | 7 | ||||
-rw-r--r-- | ext/pdo_odbc/odbc_driver.c | 6 | ||||
-rw-r--r-- | ext/pdo_pgsql/pgsql_driver.c | 1 | ||||
-rw-r--r-- | ext/pdo_sqlite/sqlite_driver.c | 22 | ||||
-rw-r--r-- | ext/pdo_sqlite/tests/gc.phpt | 24 |
10 files changed, 75 insertions, 10 deletions
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 2e81db2bbf..25ee7afb2e 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1291,8 +1291,12 @@ static int dbh_compare(zval *object1, zval *object2) static HashTable *dbh_get_gc(zend_object *object, zval **gc_data, int *gc_count) { pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(object); - *gc_data = &dbh->def_stmt_ctor_args; - *gc_count = 1; + zend_get_gc_buffer *gc_buffer = zend_get_gc_buffer_create(); + zend_get_gc_buffer_add_zval(gc_buffer, &dbh->def_stmt_ctor_args); + if (dbh->methods->get_gc) { + dbh->methods->get_gc(dbh, gc_buffer); + } + zend_get_gc_buffer_use(gc_buffer, gc_data, gc_count); return zend_std_get_properties(object); } diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 960ddec4ef..974eb0bad0 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -286,6 +286,10 @@ typedef int (*pdo_dbh_check_liveness_func)(pdo_dbh_t *dbh); * scope */ typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh); +/* Called when the PDO handle is scanned for GC. Should populate the get_gc buffer + * with any zvals in the driver_data that would be freed if the handle is destroyed. */ +typedef void (*pdo_dbh_get_gc_func)(pdo_dbh_t *dbh, zend_get_gc_buffer *buffer); + /* for adding methods to the dbh or stmt objects pointer to a list of driver specific functions. The convention is to prefix the function names using the PDO driver name; this will @@ -316,6 +320,7 @@ struct pdo_dbh_methods { pdo_dbh_get_driver_methods_func get_driver_methods; pdo_dbh_request_shutdown persistent_shutdown; pdo_dbh_txn_func in_transaction; + pdo_dbh_get_gc_func get_gc; }; /* }}} */ diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index 7f160a402f..e581642037 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -417,7 +417,8 @@ static const struct pdo_dbh_methods dblib_methods = { NULL, /* check liveness */ NULL, /* get driver methods */ NULL, /* request shutdown */ - NULL /* in transaction */ + NULL, /* in transaction */ + NULL /* get gc */ }; static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options) diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c index c27a9e2ed5..c299907f0f 100644 --- a/ext/pdo_firebird/firebird_driver.c +++ b/ext/pdo_firebird/firebird_driver.c @@ -1005,7 +1005,11 @@ static const struct pdo_dbh_methods firebird_methods = { /* {{{ */ NULL, /* last_id not supported */ pdo_firebird_fetch_error_func, firebird_handle_get_attribute, - NULL /* check_liveness */ + NULL, /* check_liveness */ + NULL, /* get driver methods */ + NULL, /* request shutdown */ + NULL, /* in transaction */ + NULL /* get gc */ }; /* }}} */ diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index a666489a50..19923464e4 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -563,7 +563,8 @@ static const struct pdo_dbh_methods mysql_methods = { pdo_mysql_check_liveness, NULL, pdo_mysql_request_shutdown, - pdo_mysql_in_transaction + pdo_mysql_in_transaction, + NULL /* get_gc */ }; /* }}} */ diff --git a/ext/pdo_oci/oci_driver.c b/ext/pdo_oci/oci_driver.c index 096a26575e..2c65fc973b 100644 --- a/ext/pdo_oci/oci_driver.c +++ b/ext/pdo_oci/oci_driver.c @@ -705,9 +705,10 @@ static const struct pdo_dbh_methods oci_methods = { pdo_oci_fetch_error_func, oci_handle_get_attribute, pdo_oci_check_liveness, /* check_liveness */ - NULL, /* get_driver_methods */ - NULL, - NULL + NULL, /* get_driver_methods */ + NULL, /* request_shutdown */ + NULL, /* in_transaction */ + NULL /* get_gc */ }; static int pdo_oci_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */ diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c index 9a254553d5..81e4915da5 100644 --- a/ext/pdo_odbc/odbc_driver.c +++ b/ext/pdo_odbc/odbc_driver.c @@ -384,7 +384,11 @@ static const struct pdo_dbh_methods odbc_methods = { NULL, /* last id */ pdo_odbc_fetch_error_func, odbc_handle_get_attr, /* get attr */ - NULL, /* check_liveness */ + NULL, /* check_liveness */ + NULL, /* get_driver_methods */ + NULL, /* request_shutdown */ + NULL, /* in_transaction */ + NULL /* get_gc */ }; static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */ diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c index d800d65a2d..37680b8efa 100644 --- a/ext/pdo_pgsql/pgsql_driver.c +++ b/ext/pdo_pgsql/pgsql_driver.c @@ -1179,6 +1179,7 @@ static const struct pdo_dbh_methods pgsql_methods = { pdo_pgsql_get_driver_methods, /* get_driver_methods */ NULL, pgsql_handle_in_transaction, + NULL /* get_gc */ }; static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ */ diff --git a/ext/pdo_sqlite/sqlite_driver.c b/ext/pdo_sqlite/sqlite_driver.c index 26fa1c00eb..a8a96c7a13 100644 --- a/ext/pdo_sqlite/sqlite_driver.c +++ b/ext/pdo_sqlite/sqlite_driver.c @@ -695,6 +695,25 @@ static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh) } } +static void pdo_sqlite_get_gc(pdo_dbh_t *dbh, zend_get_gc_buffer *gc_buffer) +{ + pdo_sqlite_db_handle *H = dbh->driver_data; + + struct pdo_sqlite_func *func = H->funcs; + while (func) { + zend_get_gc_buffer_add_zval(gc_buffer, &func->func); + zend_get_gc_buffer_add_zval(gc_buffer, &func->step); + zend_get_gc_buffer_add_zval(gc_buffer, &func->fini); + func = func->next; + } + + struct pdo_sqlite_collation *collation = H->collations; + while (collation) { + zend_get_gc_buffer_add_zval(gc_buffer, &collation->callback); + collation = collation->next; + } +} + static const struct pdo_dbh_methods sqlite_methods = { sqlite_handle_closer, sqlite_handle_preparer, @@ -710,7 +729,8 @@ static const struct pdo_dbh_methods sqlite_methods = { NULL, /* check_liveness: not needed */ get_driver_methods, pdo_sqlite_request_shutdown, - NULL + NULL, /* in_transaction */ + pdo_sqlite_get_gc }; static char *make_filename_safe(const char *filename) diff --git a/ext/pdo_sqlite/tests/gc.phpt b/ext/pdo_sqlite/tests/gc.phpt new file mode 100644 index 0000000000..25407697e6 --- /dev/null +++ b/ext/pdo_sqlite/tests/gc.phpt @@ -0,0 +1,24 @@ +--TEST-- +GC support for PDO Sqlite driver data +--SKIPIF-- +<?php +if (!extension_loaded('pdo_sqlite')) print 'skip not loaded'; +?> +--FILE-- +<?php + +class Obj { + public $a; + public function callback() { } +} + +$obj = new Obj; +$obj->a = new PDO('sqlite::memory:'); +$obj->a->sqliteCreateFunction('func1', function() use ($obj) {}, 1); +$obj->a->sqliteCreateAggregate('func2', function() use ($obj) {}, function() use($obj) {}); +$obj->a->sqliteCreateCollation('col', function() use ($obj) {}); + +?> +===DONE=== +--EXPECT-- +===DONE=== |