]> granicus.if.org Git - php/commitdiff
Finished persistent PDO implement
authorXinchen Hui <laruence@php.net>
Mon, 26 May 2014 06:17:45 +0000 (14:17 +0800)
committerXinchen Hui <laruence@php.net>
Mon, 26 May 2014 06:17:45 +0000 (14:17 +0800)
ext/pdo/pdo.c
ext/pdo/pdo_dbh.c
ext/pdo/pdo_stmt.c
ext/pdo/php_pdo_driver.h
ext/pdo/php_pdo_int.h

index b0dd27a9661a68008a26f50e3428599dcc8bbb42..3e10a6d003923077f0f51c84b111813b957eed38 100644 (file)
 
 static zend_class_entry *spl_ce_RuntimeException;
 
+zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce;
+
+/* for exceptional circumstances */
+zend_class_entry *pdo_exception_ce;
+
 ZEND_DECLARE_MODULE_GLOBALS(pdo)
 static PHP_GINIT_FUNCTION(pdo);
 
@@ -46,32 +51,33 @@ HashTable pdo_driver_hash;
 /* we use persistent resources for the driver connection stuff */
 static int le_ppdo;
 
-int php_pdo_list_entry(void)
+int php_pdo_list_entry(void) /* {{{ */
 {
        return le_ppdo;
 }
+/* }}} */
 
-/* for exceptional circumstances */
-zend_class_entry *pdo_exception_ce;
-
-PDO_API zend_class_entry *php_pdo_get_dbh_ce(void)
+PDO_API zend_class_entry *php_pdo_get_dbh_ce(void) /* {{{ */
 {
        return pdo_dbh_ce;
 }
+/* }}} */
 
-PDO_API zend_class_entry *php_pdo_get_exception(void)
+PDO_API zend_class_entry *php_pdo_get_exception(void) /* {{{ */
 {
        return pdo_exception_ce;
 }
+/* }}} */
 
-PDO_API char *php_pdo_str_tolower_dup(const char *src, int len)
+PDO_API char *php_pdo_str_tolower_dup(const char *src, int len) /* {{{ */
 {
        char *dest = emalloc(len + 1);
        zend_str_tolower_copy(dest, src, len);
        return dest;
 }
+/* }}} */
 
-PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC)
+PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC) /* {{{ */
 {
 #if defined(HAVE_SPL)
        if (!root) {
@@ -89,8 +95,7 @@ PDO_API zend_class_entry *php_pdo_get_exception_base(int root TSRMLS_DC)
 #endif
        return zend_exception_get_default(TSRMLS_C);
 }
-
-zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce;
+/* }}} */
 
 /* {{{ proto array pdo_drivers()
  Return array of available PDO drivers */
@@ -171,7 +176,7 @@ static PHP_GINIT_FUNCTION(pdo)
 }
 /* }}} */
 
-PDO_API int php_pdo_register_driver(pdo_driver_t *driver)
+PDO_API int php_pdo_register_driver(pdo_driver_t *driver) /* {{{ */
 {
        if (driver->api_version != PDO_DRIVER_API) {
                zend_error(E_ERROR, "PDO: driver %s requires PDO API version %ld; this is PDO version %d",
@@ -185,8 +190,9 @@ PDO_API int php_pdo_register_driver(pdo_driver_t *driver)
 
        return zend_hash_str_add_ptr(&pdo_driver_hash, (char*)driver->driver_name, driver->driver_name_len, driver) != NULL;
 }
+/* }}} */
 
-PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver)
+PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver) /* {{{ */
 {
        if (!zend_hash_str_exists(&module_registry, "pdo", sizeof("pdo") - 1)) {
                return;
@@ -194,15 +200,15 @@ PDO_API void php_pdo_unregister_driver(pdo_driver_t *driver)
 
        zend_hash_str_del(&pdo_driver_hash, (char*)driver->driver_name, driver->driver_name_len);
 }
+/* }}} */
 
-pdo_driver_t *pdo_find_driver(const char *name, int namelen)
+pdo_driver_t *pdo_find_driver(const char *name, int namelen) /* {{{ */
 {
        return zend_hash_str_find_ptr(&pdo_driver_hash, (char*)name, namelen);
 }
+/* }}} */
 
-PDO_API int php_pdo_parse_data_source(const char *data_source,
-               unsigned long data_source_len, struct pdo_data_src_parser *parsed,
-               int nparams)
+PDO_API int php_pdo_parse_data_source(const char *data_source, unsigned long data_source_len, struct pdo_data_src_parser *parsed, int nparams) /* {{{ */
 {
        int i, j;
        int valstart = -1;
@@ -300,9 +306,10 @@ PDO_API int php_pdo_parse_data_source(const char *data_source,
 
        return n_matches;
 }
+/* }}} */
 
 static const char digit_vec[] = "0123456789";
-PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC)
+PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC) /* {{{ */
 {
        char buffer[65];
        char outbuf[65] = "";
@@ -341,6 +348,7 @@ PDO_API char *php_pdo_int64_to_str(pdo_int64_t i64 TSRMLS_DC)
        *dst = '\0';
        return estrdup(outbuf);
 }
+/* }}} */
 
 /* {{{ PHP_MINIT_FUNCTION */
 PHP_MINIT_FUNCTION(pdo)
index 0cc6ea5cf4ec43245c08263c0ede3e0a198bf953..88f6e4e91e6a7fcfb29387b7c3daa9e6a1949508 100644 (file)
@@ -273,9 +273,6 @@ static PHP_METHOD(PDO, dbh_constructor)
                char *hashkey = NULL;
                zend_resource *le;
                pdo_dbh_t *pdbh = NULL;
-
-               //?? let's delay the persistent supports later
-#if 0
                zval *v;
 
                if ((v = zend_hash_index_find(Z_ARRVAL_P(options), PDO_ATTR_PERSISTENT)) != NULL) {
@@ -295,7 +292,6 @@ static PHP_METHOD(PDO, dbh_constructor)
                                                password ? password : "");
                        }
                }
-#endif
 
                if (is_persistent) {
                        /* let's see if we have one cached.... */
@@ -328,30 +324,15 @@ static PHP_METHOD(PDO, dbh_constructor)
                                }
                                memcpy((char *)pdbh->persistent_id, hashkey, plen+1);
                                pdbh->persistent_id_len = plen;
-                               pdbh->refcount = 1;
-                               pdbh->std.properties = NULL;
+                               pdbh->def_stmt_ce = dbh->def_stmt_ce;
                        }
                }
 
                if (pdbh) {
-                       /* let's copy the emalloc bits over from the other handle */
-                       if (pdbh->std.properties) {
-                               zend_hash_destroy(dbh->std.properties); 
-                               efree(dbh->std.properties);
-                       } else {
-                               pdbh->std.ce = dbh->std.ce;
-                               pdbh->def_stmt_ce = dbh->def_stmt_ce;
-                               ZVAL_COPY_VALUE(&pdbh->def_stmt_ctor_args, &dbh->def_stmt_ctor_args);
-                               pdbh->std.properties = dbh->std.properties;
-                               //???
-                               //pdbh->std.properties_table = dbh->std.properties_table;
-                       }
-                       /* kill the non-persistent thingamy */
                        efree(dbh);
                        /* switch over to the persistent one */
+                       Z_PDO_OBJECT_P(object)->inner = pdbh;
                        dbh = pdbh;
-                       zend_object_store_set_object(object, &dbh->std TSRMLS_CC);
-                       dbh->refcount++;
                }
 
                if (hashkey) {
@@ -391,8 +372,8 @@ static PHP_METHOD(PDO, dbh_constructor)
                        le.type = php_pdo_list_entry();
                        le.ptr = dbh;
 
-                       if (zend_hash_str_update_mem(&EG(persistent_list), 
-                                               (char*)dbh->persistent_id, dbh->persistent_id_len, &le, sizeof(le))) {
+                       if ((zend_hash_str_update_mem(&EG(persistent_list), 
+                                               (char*)dbh->persistent_id, dbh->persistent_id_len, &le, sizeof(le))) == NULL) {
                                php_error_docref(NULL TSRMLS_CC, E_ERROR, "Failed to register persistent entry");
                        }
                }
@@ -493,12 +474,13 @@ static void pdo_stmt_construct(pdo_stmt_t *stmt, zval *object, zend_class_entry
    Prepares a statement for execution and returns a statement object */
 static PHP_METHOD(PDO, prepare)
 {
-       pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
        pdo_stmt_t *stmt;
        char *statement;
        int statement_len;
        zval *options = NULL, *opt, *item, ctor_args;
        zend_class_entry *dbstmt_ce, *pce;
+       pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(getThis());
+       pdo_dbh_t *dbh = dbh_obj->inner;
 
        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|a", &statement,
                        &statement_len, &options)) {
@@ -566,7 +548,7 @@ static PHP_METHOD(PDO, prepare)
        stmt->default_fetch_type = dbh->default_fetch_type;
        stmt->dbh = dbh;
        /* give it a reference to me */
-       ZVAL_OBJ(&stmt->database_object_handle, &dbh->std);
+       ZVAL_OBJ(&stmt->database_object_handle, &dbh_obj->std);
        Z_ADDREF(stmt->database_object_handle);
        /* we haven't created a lazy object yet */
        ZVAL_UNDEF(&stmt->lazy_object_ref);
@@ -1070,10 +1052,11 @@ static PHP_METHOD(PDO, errorInfo)
    Prepare and execute $sql; returns the statement object for iteration */
 static PHP_METHOD(PDO, query)
 {
-       pdo_dbh_t *dbh = Z_PDO_DBH_P(getThis());
        pdo_stmt_t *stmt;
        char *statement;
        int statement_len;
+       pdo_dbh_object_t *dbh_obj = Z_PDO_OBJECT_P(getThis());
+       pdo_dbh_t *dbh = dbh_obj->inner;
 
        /* Return a meaningful error when no parameters were passed */
        if (!ZEND_NUM_ARGS()) {
@@ -1104,7 +1087,7 @@ static PHP_METHOD(PDO, query)
        stmt->active_query_stringlen = statement_len;
        stmt->dbh = dbh;
        /* give it a reference to me */
-       ZVAL_OBJ(&stmt->database_object_handle, &dbh->std);
+       ZVAL_OBJ(&stmt->database_object_handle, &dbh_obj->std);
        Z_ADDREF(stmt->database_object_handle);
        /* we haven't created a lazy object yet */
        ZVAL_UNDEF(&stmt->lazy_object_ref);
@@ -1247,7 +1230,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_pdo__void, 0)
 ZEND_END_ARG_INFO()
 /* }}} */
 
-const zend_function_entry pdo_dbh_functions[] = {
+const zend_function_entry pdo_dbh_functions[] = /* {{{ */ {
        ZEND_MALIAS(PDO, __construct, dbh_constructor,  arginfo_pdo___construct,        ZEND_ACC_PUBLIC)
        PHP_ME(PDO, prepare,                            arginfo_pdo_prepare,            ZEND_ACC_PUBLIC)
        PHP_ME(PDO, beginTransaction,       arginfo_pdo__void,         ZEND_ACC_PUBLIC)
@@ -1267,23 +1250,26 @@ const zend_function_entry pdo_dbh_functions[] = {
        PHP_ME(PDO, getAvailableDrivers,    arginfo_pdo__void,         ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
        {NULL, NULL, NULL}
 };
+/* }}} */
 
-static void cls_method_dtor(zval *el) {
+static void cls_method_dtor(zval *el) /* {{{ */ {
        zend_function *func = (zend_function*)Z_PTR_P(el);
        if (func->common.function_name) {
                STR_RELEASE(func->common.function_name);
        }
        efree(func);
 }
+/* }}} */
 
 /* {{{ overloaded object handlers for PDO class */
-int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
+int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind TSRMLS_DC)
 {
        const zend_function_entry *funcs;
        zend_function func;
        zend_internal_function *ifunc = (zend_internal_function*)&func;
        int namelen;
        char *lc_name;
+       pdo_dbh_t *dbh = dbh_obj->inner;
 
        if (!dbh || !dbh->methods || !dbh->methods->get_driver_methods) {
                return 0;
@@ -1302,7 +1288,7 @@ int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
                ifunc->type = ZEND_INTERNAL_FUNCTION;
                ifunc->handler = funcs->handler;
                ifunc->function_name = STR_INIT(funcs->fname, strlen(funcs->fname), 0);
-               ifunc->scope = dbh->std.ce;
+               ifunc->scope = dbh_obj->std.ce;
                ifunc->prototype = NULL;
                if (funcs->flags) {
                        ifunc->fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE;
@@ -1344,7 +1330,7 @@ int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
 static union _zend_function *dbh_method_get(zend_object **object, zend_string *method_name, const zval *key TSRMLS_DC)
 {
        zend_function *fbc = NULL;
-       pdo_dbh_t *dbh = php_pdo_dbh_fetch_object(*object);
+       pdo_dbh_object_t *dbh_obj = php_pdo_dbh_fetch_object(*object);
        zend_string *lc_method_name;
 
        lc_method_name = STR_INIT(method_name->val, method_name->len, 0);
@@ -1353,15 +1339,15 @@ static union _zend_function *dbh_method_get(zend_object **object, zend_string *m
        if ((fbc = std_object_handlers.get_method(object, method_name, key TSRMLS_CC)) == NULL) {
                /* not a pre-defined method, nor a user-defined method; check
                 * the driver specific methods */
-               if (!dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
-                       if (!pdo_hash_methods(dbh,
+               if (!dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
+                       if (!pdo_hash_methods(dbh_obj,
                                PDO_DBH_DRIVER_METHOD_KIND_DBH TSRMLS_CC)
-                               || !dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
+                               || !dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH]) {
                                goto out;
                        }
                }
 
-               fbc = zend_hash_find_ptr(dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH], lc_method_name);
+               fbc = zend_hash_find_ptr(dbh_obj->inner->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_DBH], lc_method_name);
        }
 
 out:
@@ -1386,7 +1372,7 @@ void pdo_dbh_init(TSRMLS_D)
        pdo_dbh_ce->create_object = pdo_dbh_new;
 
        memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
-       pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_t, std);
+       pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std);
        pdo_dbh_object_handlers.dtor_obj = zend_objects_destroy_object;
        pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage;
        pdo_dbh_object_handlers.get_method = dbh_method_get;
@@ -1489,10 +1475,14 @@ void pdo_dbh_init(TSRMLS_D)
 
 }
 
-static void dbh_free(pdo_dbh_t *dbh TSRMLS_DC)
+static void dbh_free(pdo_dbh_t *dbh, zend_bool free_persistent TSRMLS_DC)
 {
        int i;
 
+       if (dbh->is_persistent && !free_persistent) {
+               return;
+       }
+
        if (dbh->query_stmt) {
                zval_ptr_dtor(&dbh->query_stmt_zval);
                dbh->query_stmt = NULL;
@@ -1527,12 +1517,12 @@ static void dbh_free(pdo_dbh_t *dbh TSRMLS_DC)
                }
        }
 
-       //???pefree(dbh, dbh->is_persistent);
+       pefree(dbh, dbh->is_persistent);
 }
 
 static void pdo_dbh_free_storage(zend_object *std TSRMLS_DC)
 {
-       pdo_dbh_t *dbh = php_pdo_dbh_fetch_object(std);
+       pdo_dbh_t *dbh = php_pdo_dbh_fetch_inner(std);
        if (dbh->in_txn && dbh->methods && dbh->methods->rollback) {
                dbh->methods->rollback(dbh TSRMLS_CC);
                dbh->in_txn = 0;
@@ -1542,19 +1532,19 @@ static void pdo_dbh_free_storage(zend_object *std TSRMLS_DC)
                dbh->methods->persistent_shutdown(dbh TSRMLS_CC);
        }
        zend_object_std_dtor(std TSRMLS_CC);
-       dbh_free(dbh TSRMLS_CC);
+       dbh_free(dbh, 0 TSRMLS_CC);
 }
 
 zend_object *pdo_dbh_new(zend_class_entry *ce TSRMLS_DC)
 {
-       pdo_dbh_t *dbh;
+       pdo_dbh_object_t *dbh;
 
-       dbh = ecalloc(1, sizeof(pdo_dbh_t) + sizeof(zval) * (ce->default_properties_count - 1));
+       dbh = ecalloc(1, sizeof(pdo_dbh_object_t) + sizeof(zval) * (ce->default_properties_count - 1));
        zend_object_std_init(&dbh->std, ce TSRMLS_CC);
        object_properties_init(&dbh->std, ce);
        rebuild_object_properties(&dbh->std);
-       dbh->refcount = 1;
-       dbh->def_stmt_ce = pdo_dbstmt_ce;
+       dbh->inner = ecalloc(1, sizeof(pdo_dbh_t));
+       dbh->inner->def_stmt_ce = pdo_dbstmt_ce;
        
        dbh->std.handlers = &pdo_dbh_object_handlers;
        
@@ -1563,14 +1553,15 @@ zend_object *pdo_dbh_new(zend_class_entry *ce TSRMLS_DC)
 
 /* }}} */
 
-ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor)
+ZEND_RSRC_DTOR_FUNC(php_pdo_pdbh_dtor) /* {{{ */
 {
        if (res->ptr) {
                pdo_dbh_t *dbh = (pdo_dbh_t*)res->ptr;
-               dbh_free(dbh TSRMLS_CC);
+               dbh_free(dbh, 1 TSRMLS_CC);
                res->ptr = NULL;
        }
 }
+/* }}} */
 
 /*
  * Local variables:
index 5d291c0771b274200ac43d3606f08eacb6942121..6f74889980322a15f1b2572582a62085539d8518 100644 (file)
@@ -2229,7 +2229,7 @@ static union _zend_function *dbstmt_method_get(zend_object **object_pp, zend_str
                /* not a pre-defined method, nor a user-defined method; check
                 * the driver specific methods */
                if (!stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT]) {
-                       if (!pdo_hash_methods(stmt->dbh
+                       if (!pdo_hash_methods(Z_PDO_OBJECT_P(&stmt->database_object_handle)
                                PDO_DBH_DRIVER_METHOD_KIND_STMT TSRMLS_CC)
                                || !stmt->dbh->cls_methods[PDO_DBH_DRIVER_METHOD_KIND_STMT]) {
                                goto out;
index 0326eaa5a128a3a42a48adbfb44845dbbca47448..4818bc623202b79c4b8991cddcd508c86a3555d6 100644 (file)
 #include "php_pdo.h"
 
 /* forward declarations */
-typedef struct _pdo_dbh_t      pdo_dbh_t;
-typedef struct _pdo_stmt_t     pdo_stmt_t;
-typedef struct _pdo_row_t      pdo_row_t;
+typedef struct _pdo_dbh_t               pdo_dbh_t;
+typedef struct _pdo_dbh_object_t pdo_dbh_object_t;
+typedef struct _pdo_stmt_t              pdo_stmt_t;
+typedef struct _pdo_row_t               pdo_row_t;
 struct pdo_bound_param_data;
 
 #ifdef PHP_WIN32
@@ -425,7 +426,6 @@ enum pdo_placeholder_support {
        PDO_PLACEHOLDER_POSITIONAL=2
 };
 
-/* represents a connection to a database */
 struct _pdo_dbh_t {
        /* driver specific methods */
        struct pdo_dbh_methods *methods;
@@ -501,7 +501,11 @@ struct _pdo_dbh_t {
 
        /* defaults for fetches */
        enum pdo_fetch_type default_fetch_type;
+};
 
+/* represents a connection to a database */
+struct _pdo_dbh_object_t {
+       pdo_dbh_t *inner;
        /* these items must appear in this order at the beginning of the
        struct so that this can be cast as a zend_object.  we need this
        to allow the extending class to escape all the custom handlers
@@ -510,11 +514,16 @@ struct _pdo_dbh_t {
        zend_object std;
 };
 
-static inline pdo_dbh_t *php_pdo_dbh_fetch_object(zend_object *obj) {
-       return (pdo_dbh_t *)((char*)(obj) - XtOffsetOf(pdo_dbh_t, std));
+static inline pdo_dbh_t *php_pdo_dbh_fetch_inner(zend_object *obj) {
+       return (pdo_dbh_t *)(((pdo_dbh_object_t *)((char*)(obj) - XtOffsetOf(pdo_dbh_object_t, std)))->inner);
+}
+
+static inline pdo_dbh_object_t *php_pdo_dbh_fetch_object(zend_object *obj) {
+       return (pdo_dbh_object_t *)((char*)(obj) - XtOffsetOf(pdo_dbh_object_t, std));
 }
 
-#define Z_PDO_DBH_P(zv) php_pdo_dbh_fetch_object(Z_OBJ_P((zv)))
+#define Z_PDO_DBH_P(zv) php_pdo_dbh_fetch_inner(Z_OBJ_P((zv)))
+#define Z_PDO_OBJECT_P(zv) php_pdo_dbh_fetch_object(Z_OBJ_P((zv)))
 
 /* describes a column */
 struct pdo_column_data {
index a428a74a3a270659b2f4eaf3668a1e1c66ff1723..27cca7c29f64605c1e5bb05e073be5e4184da4e5 100644 (file)
@@ -60,7 +60,7 @@ extern pdo_driver_t *pdo_find_driver(const char *name, int namelen);
 int pdo_sqlstate_init_error_table(void);
 void pdo_sqlstate_fini_error_table(void);
 const char *pdo_sqlstate_state_to_description(char *state);
-int pdo_hash_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC);
+int pdo_hash_methods(pdo_dbh_object_t *dbh, int kind TSRMLS_DC);
 
 
 /*