scottmac Tue Jul 29 00:56:22 2008 UTC
Modified files:
/php-src/ext/sqlite3 php_sqlite3_structs.h sqlite3.c
/php-src/ext/sqlite3/tests sqlite3_12_unfinalized_stmt_cleanup.phpt
Log:
Add freelist for tracking sqlite statements to free on implicit
SQLite3::close()
http://cvs.php.net/viewvc.cgi/php-src/ext/sqlite3/php_sqlite3_structs.h?r1=1.2&r2=1.3&diff_format=u
Index: php-src/ext/sqlite3/php_sqlite3_structs.h
diff -u php-src/ext/sqlite3/php_sqlite3_structs.h:1.2
php-src/ext/sqlite3/php_sqlite3_structs.h:1.3
--- php-src/ext/sqlite3/php_sqlite3_structs.h:1.2 Mon Jul 28 09:11:19 2008
+++ php-src/ext/sqlite3/php_sqlite3_structs.h Tue Jul 29 00:56:22 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: php_sqlite3_structs.h,v 1.2 2008/07/28 09:11:19 pajoye Exp $ */
+/* $Id: php_sqlite3_structs.h,v 1.3 2008/07/29 00:56:22 scottmac Exp $ */
#ifndef PHP_SQLITE_STRUCTS_H
#define PHP_SQLITE_STRUCTS_H
@@ -68,23 +68,18 @@
int initialised;
sqlite3 *db;
php_sqlite3_func *funcs;
-} php_sqlite3_db_object;
-/*typedef struct _php_sqlite3_stmt {
- sqlite3_stmt *stmt;
- int initialised;
-} php_sqlite3_stmt;*/
+ zend_llist free_list;
+} php_sqlite3_db_object;
typedef struct _php_sqlite3_stmt_object php_sqlite3_stmt;
typedef struct _php_sqlite3_result_object php_sqlite3_result;
/* sqlite3 objects to be destroyed */
-typedef struct _php_sqlite3_stmt_free_list {
- sqlite3_stmt *stmt;
-
- zval *statement_object;
- zval *result_object;
-} php_sqlite3_stmt_free_list;
+typedef struct _php_sqlite3_free_list {
+ zval *stmt_obj_zval;
+ php_sqlite3_stmt *stmt_obj;
+} php_sqlite3_free_list;
/* Structure for SQLite Result object. */
struct _php_sqlite3_result_object {
@@ -92,8 +87,6 @@
php_sqlite3_db_object *db_obj;
php_sqlite3_stmt *stmt_obj;
zval *stmt_obj_zval;
-
- int initialised;
int is_prepared_statement;
int complete;
http://cvs.php.net/viewvc.cgi/php-src/ext/sqlite3/sqlite3.c?r1=1.6&r2=1.7&diff_format=u
Index: php-src/ext/sqlite3/sqlite3.c
diff -u php-src/ext/sqlite3/sqlite3.c:1.6 php-src/ext/sqlite3/sqlite3.c:1.7
--- php-src/ext/sqlite3/sqlite3.c:1.6 Mon Jul 28 23:03:26 2008
+++ php-src/ext/sqlite3/sqlite3.c Tue Jul 29 00:56:22 2008
@@ -16,7 +16,7 @@
+----------------------------------------------------------------------+
*/
-/* $Id: sqlite3.c,v 1.6 2008/07/28 23:03:26 scottmac Exp $ */
+/* $Id: sqlite3.c,v 1.7 2008/07/29 00:56:22 scottmac Exp $ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -39,7 +39,7 @@
static PHP_GINIT_FUNCTION(sqlite3);
static int php_sqlite3_authorizer(void *autharg, int access_type, const char
*arg3, const char *arg4, const char *arg5, const char *arg6);
static void sqlite3_param_dtor(void *data);
-static int php_sqlite3_compare_stmt_free( php_sqlite3_stmt_free_list
**stmt_list, sqlite3_stmt *statement );
+static int php_sqlite3_compare_stmt_zval_free( php_sqlite3_free_list
**free_list, zval *statement );
#define SQLITE3_CHECK_INITIALIZED(member, class_name) \
if (!(member)) { \
@@ -160,6 +160,7 @@
}
if (db_obj->initialised) {
+ zend_llist_clean(&(db_obj->free_list));
errcode = sqlite3_close(db_obj->db);
if (errcode != SQLITE_OK) {
RETURN_TRUE;
@@ -409,6 +410,7 @@
zval_dtor(return_value);
RETURN_FALSE;
}
+ stmt_obj->initialised = 1;
}
/* }}} */
@@ -462,31 +464,32 @@
RETURN_FALSE;
}
+ stmt_obj->initialised = 1;
+
object_init_ex(return_value, php_sqlite3_result_entry);
result = (php_sqlite3_result
*)zend_object_store_get_object(return_value TSRMLS_CC);
result->db_obj = db_obj;
result->stmt_obj = stmt_obj;
result->stmt_obj_zval = stmt;
- result->initialised = 1;
return_code = sqlite3_step(result->stmt_obj->stmt);
switch (return_code) {
case SQLITE_ROW: /* Valid Row */
case SQLITE_DONE: /* Valid but no results */
{
- /*php_sqlite3_stmt_free_list *free_item;
- free_item = emalloc(sizeof(php_sqlite3_stmt_free_list));
- free_item->stmt = result->intern_stmt;
- free_item->statement_object = NULL;
- free_item->result_object = return_value;
- zend_llist_add_element(&(db_obj->stmt_list),
&free_item);*/
+ php_sqlite3_free_list *free_item;
+ free_item = emalloc(sizeof(php_sqlite3_free_list));
+ free_item->stmt_obj = stmt_obj;
+ free_item->stmt_obj_zval = stmt;
+ zend_llist_add_element(&(db_obj->free_list),
&free_item);
sqlite3_reset(result->stmt_obj->stmt);
break;
}
default:
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to
execute statement: %s", sqlite3_errmsg(db_obj->db));
- sqlite3_finalize(result->stmt_obj->stmt);
+ sqlite3_finalize(stmt_obj->stmt);
+ stmt_obj->initialised = 0;
zval_dtor(return_value);
RETURN_FALSE;
}
@@ -917,7 +920,7 @@
return;
}
- /*zend_llist_del_element(&(stmt_obj->db_obj->stmt_list),
stmt_obj->stmt, (int (*)(void *, void *)) php_sqlite3_compare_stmt_free);*/
+ zend_llist_del_element(&(stmt_obj->db_obj->free_list), object, (int
(*)(void *, void *)) php_sqlite3_compare_stmt_zval_free);
RETURN_TRUE;
}
@@ -1156,6 +1159,8 @@
case SQLITE_ROW: /* Valid Row */
case SQLITE_DONE: /* Valid but no results */
{
+ php_sqlite3_free_list *free_item;
+
sqlite3_reset(stmt_obj->stmt);
object_init_ex(return_value, php_sqlite3_result_entry);
result = (php_sqlite3_result
*)zend_object_store_get_object(return_value TSRMLS_CC);
@@ -1163,11 +1168,16 @@
Z_ADDREF_P(object);
result->is_prepared_statement = 1;
- result->initialised = 1;
result->db_obj = stmt_obj->db_obj;
result->stmt_obj = stmt_obj;
result->stmt_obj_zval = getThis();
+ free_item = emalloc(sizeof(php_sqlite3_free_list));
+ free_item->stmt_obj = stmt_obj;
+ free_item->stmt_obj_zval = getThis();
+
+ zend_llist_add_element(&(stmt_obj->db_obj->free_list),
&free_item);
+
break;
}
case SQLITE_ERROR:
@@ -1191,7 +1201,7 @@
zval *object = getThis();
result_obj = (php_sqlite3_result *)zend_object_store_get_object(object
TSRMLS_CC);
- SQLITE3_CHECK_INITIALIZED(result_obj->initialised, SQLite3_result)
+ SQLITE3_CHECK_INITIALIZED(result_obj->stmt_obj->initialised,
SQLite3_result)
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1210,7 +1220,7 @@
int column = 0;
result_obj = (php_sqlite3_result *)zend_object_store_get_object(object
TSRMLS_CC);
- SQLITE3_CHECK_INITIALIZED(result_obj->initialised, SQLite3_result)
+ SQLITE3_CHECK_INITIALIZED(result_obj->stmt_obj->initialised,
SQLite3_result)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &column) ==
FAILURE) {
return;
@@ -1229,7 +1239,7 @@
int column = 0;
result_obj = (php_sqlite3_result *)zend_object_store_get_object(object
TSRMLS_CC);
- SQLITE3_CHECK_INITIALIZED(result_obj->initialised, SQLite3_result)
+ SQLITE3_CHECK_INITIALIZED(result_obj->stmt_obj->initialised,
SQLite3_result)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &column) ==
FAILURE) {
return;
@@ -1248,7 +1258,7 @@
int i, ret, mode = PHP_SQLITE3_BOTH;
result_obj = (php_sqlite3_result *)zend_object_store_get_object(object
TSRMLS_CC);
- SQLITE3_CHECK_INITIALIZED(result_obj->initialised, SQLite3_result)
+ SQLITE3_CHECK_INITIALIZED(result_obj->stmt_obj->initialised,
SQLite3_result)
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &mode) ==
FAILURE) {
return;
@@ -1301,7 +1311,7 @@
zval *object = getThis();
result_obj = (php_sqlite3_result *)zend_object_store_get_object(object
TSRMLS_CC);
- SQLITE3_CHECK_INITIALIZED(result_obj->initialised, SQLite3_result)
+ SQLITE3_CHECK_INITIALIZED(result_obj->stmt_obj->initialised,
SQLite3_result)
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1325,7 +1335,7 @@
zval *object = getThis();
result_obj = (php_sqlite3_result *)zend_object_store_get_object(object
TSRMLS_CC);
- SQLITE3_CHECK_INITIALIZED(result_obj->initialised, SQLite3_result)
+ SQLITE3_CHECK_INITIALIZED(result_obj->stmt_obj->initialised,
SQLite3_result)
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1333,8 +1343,8 @@
/* We need to finalize an internal statement */
if (result_obj->is_prepared_statement == 0) {
- result_obj->initialised = 0;
- sqlite3_finalize(result_obj->stmt_obj->stmt);
+ zend_llist_del_element(&(result_obj->db_obj->free_list),
result_obj->stmt_obj_zval,
+ (int (*)(void *, void *))
php_sqlite3_compare_stmt_zval_free);
} else {
sqlite3_reset(result_obj->stmt_obj->stmt);
}
@@ -1554,25 +1564,29 @@
}
/* }}} */
-/* {{{ php_sqlite3_stmt_free
+/* {{{ php_sqlite3_free_list_dtor
*/
-static void php_sqlite3_stmt_free(void **item)
+static void php_sqlite3_free_list_dtor(void **item)
{
- php_sqlite3_stmt_free_list *free_item = (php_sqlite3_stmt_free_list
*)*item;
+ php_sqlite3_free_list *free_item = (php_sqlite3_free_list *)*item;
- zval_dtor(free_item->result_object);
- Z_TYPE_P(free_item->result_object) = IS_NULL;
- if (free_item->statement_object) {
- zval_dtor(free_item->statement_object);
- Z_TYPE_P(free_item->statement_object) = IS_NULL;
+ if (free_item->stmt_obj && free_item->stmt_obj->initialised) {
+ sqlite3_finalize(free_item->stmt_obj->stmt);
+ free_item->stmt_obj->initialised = 0;
}
efree(*item);
}
/* }}} */
-static int php_sqlite3_compare_stmt_free( php_sqlite3_stmt_free_list
**stmt_list, sqlite3_stmt *statement ) /* {{{ */
+static int php_sqlite3_compare_stmt_zval_free( php_sqlite3_free_list
**free_list, zval *statement ) /* {{{ */
{
- return (statement == (*stmt_list)->stmt);
+ return ((*free_list)->stmt_obj->initialised && statement ==
(*free_list)->stmt_obj_zval);
+}
+/* }}} */
+
+static int php_sqlite3_compare_stmt_free( php_sqlite3_free_list **free_list,
sqlite3_stmt *statement ) /* {{{ */
+{
+ return ((*free_list)->stmt_obj->initialised && statement ==
(*free_list)->stmt_obj->stmt);
}
/* }}} */
@@ -1631,8 +1645,8 @@
}
if (intern->initialised) {
- intern->initialised = 0;
- sqlite3_finalize(intern->stmt);
+ zend_llist_del_element(&(intern->db_obj->free_list),
intern->stmt,
+ (int (*)(void *, void *))
php_sqlite3_compare_stmt_free);
}
Z_DELREF_P(intern->db_obj_zval);
@@ -1676,8 +1690,8 @@
intern = emalloc(sizeof(php_sqlite3_db_object));
memset(&intern->zo, 0, sizeof(php_sqlite3_db_object));
- /* Non standard stuff, not sure if this is really required still
- zend_llist_init(&(intern->stmt_list),
sizeof(php_sqlite3_stmt_free_list *), (llist_dtor_func_t)php_sqlite3_stmt_free,
0);*/
+ /* Need to keep track of things to free */
+ zend_llist_init(&(intern->free_list), sizeof(php_sqlite3_free_list
*), (llist_dtor_func_t)php_sqlite3_free_list_dtor, 0);
zend_object_std_init(&intern->zo, class_type TSRMLS_CC);
zend_hash_copy(intern->zo.properties, &class_type->default_properties,
(copy_ctor_func_t) zval_add_ref,(void *) &tmp, sizeof(zval *));
http://cvs.php.net/viewvc.cgi/php-src/ext/sqlite3/tests/sqlite3_12_unfinalized_stmt_cleanup.phpt?r1=1.2&r2=1.3&diff_format=u
Index: php-src/ext/sqlite3/tests/sqlite3_12_unfinalized_stmt_cleanup.phpt
diff -u php-src/ext/sqlite3/tests/sqlite3_12_unfinalized_stmt_cleanup.phpt:1.2
php-src/ext/sqlite3/tests/sqlite3_12_unfinalized_stmt_cleanup.phpt:1.3
--- php-src/ext/sqlite3/tests/sqlite3_12_unfinalized_stmt_cleanup.phpt:1.2
Fri Jul 25 21:34:15 2008
+++ php-src/ext/sqlite3/tests/sqlite3_12_unfinalized_stmt_cleanup.phpt Tue Jul
29 00:56:22 2008
@@ -26,8 +26,8 @@
echo "Closing database\n";
var_dump($db->close());
-echo "Check result was freed\n";
-var_dump($results);
+echo "Check db was closed\n";
+var_dump($results->numColumns());
echo "Done\n";
?>
--EXPECTF--
@@ -45,6 +45,8 @@
}
Closing database
bool(true)
-Check result was freed
-NULL
+Check db was closed
+
+Warning: SQLite3_result::numColumns(): The SQLite3_result object has not been
correctly initialised in %s on line %d
+bool(false)
Done
--
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php