]> granicus.if.org Git - php/commitdiff
Fix a dumb bug that would effecively ignore persistent connections and create a
authorWez Furlong <wez@php.net>
Fri, 10 Jun 2005 05:47:55 +0000 (05:47 +0000)
committerWez Furlong <wez@php.net>
Fri, 10 Jun 2005 05:47:55 +0000 (05:47 +0000)
new one each time.

Add a hook for persistent connections: it is called when the object goes out of
scope, and offers the driver an opportunity to release per-request scoped data
at the right time.

This hook is used by pdo_sqlite to unregister UDFs, which are dangerous to keep
registered between requests.

ext/pdo/pdo_dbh.c
ext/pdo/php_pdo_driver.h

index 15e2384ebb3cb51d1e93d2e1dc9b66c6224cd3c3..09421863a54faf62dfcffccaeba0e7d80faefb4a 100755 (executable)
@@ -216,6 +216,7 @@ static PHP_FUNCTION(dbh_constructor)
        pdo_driver_t *driver = NULL;
        zval *options = NULL;
        char alt_dsn[512];
+       int call_factory = 1;
 
        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ssa!", &data_source, &data_source_len,
                                &username, &usernamelen, &password, &passwordlen, &options)) {
@@ -300,35 +301,39 @@ static PHP_FUNCTION(dbh_constructor)
                        }
                }
 
-               /* let's see if we have one cached.... */
-               if (is_persistent && SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, plen+1, (void*)&le)) {
-                       if (Z_TYPE_P(le) == php_pdo_list_entry()) {
-                               pdbh = (pdo_dbh_t*)le->ptr;
-
-                               /* is the connection still alive ? */
-                               if (pdbh->methods->check_liveness && FAILURE == (pdbh->methods->check_liveness)(pdbh TSRMLS_CC)) {
-                                       /* nope... need to kill it */
-                                       pdbh = NULL;
+               if (is_persistent) {
+                       /* let's see if we have one cached.... */
+                       if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, plen+1, (void*)&le)) {
+                               if (Z_TYPE_P(le) == php_pdo_list_entry()) {
+                                       pdbh = (pdo_dbh_t*)le->ptr;
+
+                                       /* is the connection still alive ? */
+                                       if (pdbh->methods->check_liveness && FAILURE == (pdbh->methods->check_liveness)(pdbh TSRMLS_CC)) {
+                                               /* nope... need to kill it */
+                                               pdbh = NULL;
+                                       }
                                }
                        }
-               }
 
-               if (is_persistent && !pdbh) {
-                       /* need a brand new pdbh */
-                       pdbh = pecalloc(1, sizeof(*pdbh), 1);
+                       if (pdbh) {
+                               call_factory = 0;
+                       } else {
+                               /* need a brand new pdbh */
+                               pdbh = pecalloc(1, sizeof(*pdbh), 1);
+
+                               if (!pdbh) {
+                                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory while allocating PDO handle");
+                                       /* NOTREACHED */
+                               }
 
-                       if (!pdbh) {
-                               php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory while allocating PDO handle");
-                               /* NOTREACHED */
-                       }
-                       
-                       pdbh->is_persistent = 1;
-                       if (!(pdbh->persistent_id = pemalloc(plen + 1, 1))) {
-                               php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory while allocating PDO handle");
+                               pdbh->is_persistent = 1;
+                               if (!(pdbh->persistent_id = pemalloc(plen + 1, 1))) {
+                                       php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory while allocating PDO handle");
+                               }
+                               memcpy((char *)pdbh->persistent_id, hashkey, plen+1);
+                               pdbh->persistent_id_len = plen+1;
+                               pdbh->refcount = 1;
                        }
-                       memcpy((char *)pdbh->persistent_id, hashkey, plen+1);
-                       pdbh->persistent_id_len = plen+1;
-                       pdbh->refcount = 1;
                }
 
                if (pdbh) {
@@ -358,7 +363,12 @@ static PHP_FUNCTION(dbh_constructor)
        if (!dbh->data_source || (username && !dbh->username) || (password && !dbh->password)) {
                php_error_docref(NULL TSRMLS_CC, E_ERROR, "out of memory");
        }
-       
+
+       if (!call_factory) {
+               /* we got a persistent guy from our cache */
+               return;
+       }
+
        if (driver->db_handle_factory(dbh, options TSRMLS_CC)) {
                /* all set */
 
@@ -1106,6 +1116,14 @@ static void dbh_free(pdo_dbh_t *dbh TSRMLS_DC)
 
 static void pdo_dbh_free_storage(pdo_dbh_t *dbh TSRMLS_DC)
 {
+       if (dbh->methods->rollback) {
+               /* roll back transactions, that are possibly nested, even though we don't
+                * official support them */
+               while (dbh->methods->rollback(dbh TSRMLS_CC))
+                       ;
+               dbh->in_txn = 0;
+       }
+       
        if (dbh->properties) {
                zend_hash_destroy(dbh->properties);
                efree(dbh->properties);
@@ -1114,6 +1132,8 @@ static void pdo_dbh_free_storage(pdo_dbh_t *dbh TSRMLS_DC)
 
        if (!dbh->is_persistent) {
                dbh_free(dbh TSRMLS_CC);
+       } else if (dbh->methods->persistent_shutdown) {
+               dbh->methods->persistent_shutdown(dbh TSRMLS_CC);
        }
 }
 
index 2036a1381dd284863017a535b8dfefc3dd51bb39..4d86cdeb598d1a65cd62c5a8695876aadb8f0b91 100755 (executable)
@@ -44,7 +44,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC);
 # define FALSE 0
 #endif
 
-#define PDO_DRIVER_API 20050227
+#define PDO_DRIVER_API 20050610
 
 enum pdo_param_type {
        PDO_PARAM_NULL,
@@ -262,6 +262,11 @@ typedef int (*pdo_dbh_get_attr_func)(pdo_dbh_t *dbh, long attr, zval *val TSRMLS
  * You may set this handler to NULL, which is equivalent to returning SUCCESS. */
 typedef int (*pdo_dbh_check_liveness_func)(pdo_dbh_t *dbh TSRMLS_DC);
 
+/* called at request end for each persistent dbh; this gives the driver
+ * the opportunity to safely release resources that only have per-request
+ * scope */
+typedef void (*pdo_dbh_request_shutdown)(pdo_dbh_t *dbh TSRMLS_DC);
+
 /* 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
@@ -290,6 +295,7 @@ struct pdo_dbh_methods {
        pdo_dbh_get_attr_func           get_attribute;
        pdo_dbh_check_liveness_func     check_liveness;
        pdo_dbh_get_driver_methods_func get_driver_methods;
+       pdo_dbh_request_shutdown        persistent_shutdown;
 };
 
 /* }}} */
@@ -473,7 +479,7 @@ struct pdo_column_data {
        unsigned long precision;
 
        /* don't touch this unless your name is dbdo */
-       void *dbdo_stuff;
+       void *dbdo_data;
 };
 
 /* describes a bound parameter */