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);
}
* 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
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;
};
/* }}} */
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)
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 */
};
/* }}} */
pdo_mysql_check_liveness,
NULL,
pdo_mysql_request_shutdown,
- pdo_mysql_in_transaction
+ pdo_mysql_in_transaction,
+ NULL /* get_gc */
};
/* }}} */
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) /* {{{ */
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) /* {{{ */
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) /* {{{ */
}
}
+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,
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)
--- /dev/null
+--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===