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

Reply via email to