Index: ext/pdo/pdo_stmt.c =================================================================== RCS file: /repository/php-src/ext/pdo/pdo_stmt.c,v retrieving revision 1.118.2.8 diff -u -p -d -r1.118.2.8 pdo_stmt.c --- ext/pdo/pdo_stmt.c 10 Oct 2005 14:44:16 -0000 1.118.2.8 +++ ext/pdo/pdo_stmt.c 22 Oct 2005 14:45:22 -0000 @@ -69,9 +69,9 @@ ZEND_END_ARG_INFO(); /* }}} */ #endif -static PHP_FUNCTION(dbstmt_constructor) /* {{{ */ +static PHP_FUNCTION(dbrow_constructor) /* {{{ */ { - php_error_docref(NULL TSRMLS_CC, E_ERROR, "You should not create a PDOStatement manually"); + php_error_docref(NULL TSRMLS_CC, E_ERROR, "You should not create a PDORow manually"); } /* }}} */ @@ -218,12 +218,17 @@ int pdo_stmt_describe_columns(pdo_stmt_t static void get_lazy_object(pdo_stmt_t *stmt, zval *return_value TSRMLS_DC) /* {{{ */ { - if (Z_TYPE(stmt->lazy_object_ref) == IS_NULL) { - Z_TYPE(stmt->lazy_object_ref) = IS_OBJECT; - Z_OBJ_HANDLE(stmt->lazy_object_ref) = zend_objects_store_put(stmt, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_row_free_storage, NULL TSRMLS_CC); - Z_OBJ_HT(stmt->lazy_object_ref) = &pdo_row_object_handlers; - /* stmt->refcount++; */ - } + pdo_row_t *row; + + row = emalloc(sizeof(pdo_row_t)); + row->stmt = stmt; + row->values = NULL; + + Z_TYPE(stmt->lazy_object_ref) = IS_OBJECT; + Z_OBJ_HANDLE(stmt->lazy_object_ref) = zend_objects_store_put(row, (zend_objects_store_dtor_t)pdo_row_destroy_object, (zend_objects_free_object_storage_t)pdo_row_free_storage, NULL TSRMLS_CC); + Z_OBJ_HT(stmt->lazy_object_ref) = &pdo_row_object_handlers; + stmt->refcount++; + Z_TYPE_P(return_value) = IS_OBJECT; Z_OBJ_HANDLE_P(return_value) = Z_OBJ_HANDLE(stmt->lazy_object_ref); Z_OBJ_HT_P(return_value) = Z_OBJ_HT(stmt->lazy_object_ref); @@ -329,6 +334,12 @@ static int really_register_bound_param(s } /* }}} */ +static PHP_METHOD (PDOStatement, __construct) /* {{{ */ +{ + php_error_docref(NULL TSRMLS_CC, E_ERROR, "You should not create a PDOStatement manually"); +} +/* }}} */ + /* {{{ proto bool PDOStatement::execute([array $bound_input_params]) Execute a prepared statement, optionally binding parameters */ static PHP_METHOD(PDOStatement, execute) @@ -1889,6 +1900,7 @@ static PHP_METHOD(PDOStatement, __sleep) /* }}} */ function_entry pdo_dbstmt_functions[] = { + PHP_ME(PDOStatement, __construct, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, execute, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, fetch, NULL, ZEND_ACC_PUBLIC) PHP_ME(PDOStatement, bindParam, second_arg_force_ref, ZEND_ACC_PUBLIC) @@ -2222,23 +2234,36 @@ function_entry pdo_row_functions[] = { static zval *row_prop_or_dim_read(zval *object, zval *member, int type TSRMLS_DC) { zval *return_value; - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); + pdo_row_t *row = (pdo_row_t *) zend_object_store_get_object(object TSRMLS_CC); int colno = -1; MAKE_STD_ZVAL(return_value); if (Z_TYPE_P(member) == IS_LONG) { - if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count) { - fetch_value(stmt, return_value, Z_LVAL_P(member), NULL TSRMLS_CC); + if (Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < row->stmt->column_count) { + fetch_value(row->stmt, return_value, Z_LVAL_P(member), NULL TSRMLS_CC); } } else { convert_to_string(member); - /* TODO: replace this with a hash of available column names to column - * numbers */ - for (colno = 0; colno < stmt->column_count; colno++) { - if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { - fetch_value(stmt, return_value, colno, NULL TSRMLS_CC); - break; + if (row->values) { + zval **tmp; + /* we have values hash, using it instead of fetching the value */ + if (zend_hash_find(row->values, Z_STRVAL_P(member), Z_STRLEN_P(member) + 1, (void **)&tmp) == SUCCESS) { + *return_value = **tmp; + zval_copy_ctor(return_value); + } + else { + ZVAL_NULL(return_value); + } + } + else { + /* TODO: replace this with a hash of available column names to column + * numbers */ + for (colno = 0; colno < row->stmt->column_count; colno++) { + if (strcmp(row->stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { + fetch_value(row->stmt, return_value, colno, NULL TSRMLS_CC); + break; + } } } } @@ -2256,18 +2281,18 @@ static void row_prop_or_dim_write(zval * static int row_prop_or_dim_exists(zval *object, zval *member, int check_empty TSRMLS_DC) { - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); + pdo_row_t *row = (pdo_row_t *) zend_object_store_get_object(object TSRMLS_CC); int colno = -1; if (Z_TYPE_P(member) == IS_LONG) { - return Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < stmt->column_count; + return Z_LVAL_P(member) >= 0 && Z_LVAL_P(member) < row->stmt->column_count; } else { convert_to_string(member); /* TODO: replace this with a hash of available column names to column * numbers */ - for (colno = 0; colno < stmt->column_count; colno++) { - if (strcmp(stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { + for (colno = 0; colno < row->stmt->column_count; colno++) { + if (strcmp(row->stmt->columns[colno].name, Z_STRVAL_P(member)) == 0) { return 1; } } @@ -2283,28 +2308,21 @@ static void row_prop_or_dim_delete(zval static HashTable *row_get_properties(zval *object TSRMLS_DC) { - zval *tmp; - pdo_stmt_t * stmt = (pdo_stmt_t *) zend_object_store_get_object(object TSRMLS_CC); + pdo_row_t *row = (pdo_row_t *) zend_object_store_get_object(object TSRMLS_CC); int i; - HashTable *ht; - - MAKE_STD_ZVAL(tmp); - array_init(tmp); - - for (i = 0; i < stmt->column_count; i++) { - zval *val; - MAKE_STD_ZVAL(val); - fetch_value(stmt, val, i, NULL TSRMLS_CC); - add_assoc_zval(tmp, stmt->columns[i].name, val); + if (!row->values) { + ALLOC_HASHTABLE(row->values); + zend_hash_init(row->values, 0, NULL, ZVAL_PTR_DTOR, 0); + + for (i = 0; i < row->stmt->column_count; i++) { + zval *val; + MAKE_STD_ZVAL(val); + fetch_value(row->stmt, val, i, NULL TSRMLS_CC); + zend_hash_update(row->values, row->stmt->columns[i].name, strlen(row->stmt->columns[i].name) + 1, &val, sizeof(zval **), NULL); + } } - - ht = Z_ARRVAL_P(tmp); - - ZVAL_NULL(tmp); - FREE_ZVAL(tmp); - - return ht; + return row->values; } static union _zend_function *row_method_get( @@ -2342,7 +2360,7 @@ static union _zend_function *row_get_cto ctor.type = ZEND_INTERNAL_FUNCTION; ctor.function_name = "__construct"; ctor.scope = pdo_row_ce; - ctor.handler = ZEND_FN(dbstmt_constructor); + ctor.handler = ZEND_FN(dbrow_constructor); return (union _zend_function*)&ctor; } @@ -2388,22 +2406,33 @@ zend_object_handlers pdo_row_object_hand NULL }; -void pdo_row_free_storage(pdo_stmt_t *stmt TSRMLS_DC) +void pdo_row_destroy_object(void *object, zend_object_handle handle TSRMLS_DC) { -#if 0 - ZVAL_NULL(&stmt->lazy_object_ref); + pdo_row_t *row = (pdo_row_t *)object; - if (--stmt->refcount == 0) { - free_statement(stmt TSRMLS_CC); + if (row && row->stmt && --row->stmt->refcount == 0) { + free_statement(row->stmt TSRMLS_CC); } -#endif +} + +void pdo_row_free_storage(pdo_row_t *row TSRMLS_DC) +{ + if (!row) { + return; + } + + if (row->values) { + zend_hash_destroy(row->values); + FREE_HASHTABLE(row->values); + } + efree(row); } zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC) { zend_object_value retval; - retval.handle = zend_objects_store_put(NULL, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t)pdo_row_free_storage, NULL TSRMLS_CC); + retval.handle = zend_objects_store_put(NULL, (zend_objects_store_dtor_t)pdo_row_destroy_object, (zend_objects_free_object_storage_t)pdo_row_free_storage, NULL TSRMLS_CC); retval.handlers = &pdo_row_object_handlers; return retval; Index: ext/pdo/php_pdo_driver.h =================================================================== RCS file: /repository/php-src/ext/pdo/php_pdo_driver.h,v retrieving revision 1.66.2.3 diff -u -p -d -r1.66.2.3 php_pdo_driver.h --- ext/pdo/php_pdo_driver.h 2 Oct 2005 22:11:17 -0000 1.66.2.3 +++ ext/pdo/php_pdo_driver.h 22 Oct 2005 14:45:22 -0000 @@ -183,7 +183,7 @@ enum pdo_null_handling { }; /* {{{ utils for reading attributes set as driver_options */ -static inline long pdo_attr_lval(zval *options, enum pdo_fetch_type option_name, long defval TSRMLS_DC) +static inline long pdo_attr_lval(zval *options, enum pdo_attribute_type option_name, long defval TSRMLS_DC) { zval **v; @@ -609,6 +609,13 @@ struct _pdo_stmt_t { const char *named_rewrite_template; }; +typedef struct _pdo_row_t { + /* parent statement */ + pdo_stmt_t *stmt; + /* row values */ + HashTable *values; +} pdo_row_t; + /* call this in MINIT to register your PDO driver */ PDO_API int php_pdo_register_driver(pdo_driver_t *driver); /* call this in MSHUTDOWN to unregister your PDO driver */ Index: ext/pdo/php_pdo_int.h =================================================================== RCS file: /repository/php-src/ext/pdo/php_pdo_int.h,v retrieving revision 1.17.2.4 diff -u -p -d -r1.17.2.4 php_pdo_int.h --- ext/pdo/php_pdo_int.h 2 Oct 2005 22:11:17 -0000 1.17.2.4 +++ ext/pdo/php_pdo_int.h 22 Oct 2005 14:45:22 -0000 @@ -48,7 +48,8 @@ int pdo_stmt_setup_fetch_mode(INTERNAL_F extern zend_object_value pdo_row_new(zend_class_entry *ce TSRMLS_DC); extern function_entry pdo_row_functions[]; extern zend_class_entry *pdo_row_ce; -void pdo_row_free_storage(pdo_stmt_t *stmt TSRMLS_DC); +void pdo_row_destroy_object(void *object, zend_object_handle handle TSRMLS_DC); +void pdo_row_free_storage(pdo_row_t *row TSRMLS_DC); extern zend_object_handlers pdo_row_object_handlers; zend_object_iterator *php_pdo_dbstmt_iter_get(zend_class_entry *ce, zval *object TSRMLS_DC);