summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/pdo/pdo_dbh.c8
-rw-r--r--ext/pdo/php_pdo_driver.h5
-rw-r--r--ext/pdo_dblib/dblib_driver.c3
-rw-r--r--ext/pdo_firebird/firebird_driver.c6
-rw-r--r--ext/pdo_mysql/mysql_driver.c3
-rw-r--r--ext/pdo_oci/oci_driver.c7
-rw-r--r--ext/pdo_odbc/odbc_driver.c6
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c1
-rw-r--r--ext/pdo_sqlite/sqlite_driver.c22
-rw-r--r--ext/pdo_sqlite/tests/gc.phpt24
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===