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