|
|||||||||||
|
PHP mysqlnd svn commit: r773 - in trunk: mysqlnd tests/ext/mysqli
From: <ahristov(at)mysql.com>
Date: Tue Jul 17 2007 - 08:36:35 EDT
Modified: trunk/mysqlnd/mysqlnd.h trunk/mysqlnd/mysqlnd_enum_n_def.h trunk/mysqlnd/mysqlnd_palloc.c trunk/mysqlnd/mysqlnd_ps.c trunk/mysqlnd/mysqlnd_ps_codec.c trunk/mysqlnd/mysqlnd_result.c trunk/tests/ext/mysqli/009.phpt Log: Fixes of two crashes and memory problems. Now PS are less effective but work without problems. Data for bound variables has to be separated! If you wanted to use PS effectively then mysqli_stmt_get_result() is your friend. Modified: trunk/mysqlnd/mysqlnd.h
/* There two should not be used from outside */ void * mysqlnd_palloc_get_zval(MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool *allocated); -void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const cache, zend_bool ps, - zend_bool *copy_ctor_called TSRMLS_DC); +void mysqlnd_palloc_zval_ptr_dtor(zval **zv, MYSQLND_THD_ZVAL_PCACHE * const cache, + enum_mysqlnd_res_type type, zend_bool *copy_ctor_called TSRMLS_DC); Modified: trunk/mysqlnd/mysqlnd_enum_n_def.h
typedef enum mysqlnd_option Modified: trunk/mysqlnd/mysqlnd_palloc.c
/* {{{ mysqlnd_palloc_zval_ptr_dtor */
MYSQLND_ZVAL_PCACHE *cache;
- php_printf("[mysqlnd_palloc_zval_ptr_dtor %p] parent_block=%p last_in_block=%p *zv=%p ps=%d refc=%d\n",
+ php_printf("[mysqlnd_palloc_zval_ptr_dtor %p] parent_block=%p last_in_block=%p *zv=%p type=%d refc=%d\n",
thd_cache,
thd_cache->parent? thd_cache->parent->block:NULL,
thd_cache->parent? thd_cache->parent->last_in_block:NULL,
- *zv, ps, ZVAL_REFCOUNT(*zv));
+ *zv, type, ZVAL_REFCOUNT(*zv));
#endif
*copy_ctor_called = FALSE;
/* Check whether cache is used and the zval is from the cache */
if (!thd_cache || !(cache = thd_cache->parent) || ((char *)*zv < (char *)thd_cache->parent->block ||
(char *)*zv > (char *)thd_cache->parent->last_in_block)) {
- /*
+ /*
This zval is not from the cache block.
Thus the refcount is -1 than of a zval from the cache,
because the zvals from the cache are owned by it.
*/
- if (ps == TRUE) {
- ZVAL_REFCOUNT(*zv) = 1;
+ if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
+ ZVAL_REFCOUNT(*zv) = 1;
} else if (ZVAL_REFCOUNT(*zv) > 1) {
- if (ps == FALSE) {
- /*
- Not a prepared statement, then we have to
- call copy_ctor and then zval_ptr_dtor()
+ /*
+ Not a prepared statement, then we have to
+ call copy_ctor and then zval_ptr_dtor()
- In Unicode mode the destruction of the zvals should not call
- zval_copy_ctor() because then we will leak.
- I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set
- to check if we need to call copy_ctor().
+ In Unicode mode the destruction of the zvals should not call
+ zval_copy_ctor() because then we will leak.
+ I suppose we can use UG(unicode) in mysqlnd.c when freeing a result set
+ to check if we need to call copy_ctor().
- If the type is IS_UNICODE, which can happen with PHP6, then we don't
- need to copy_ctor, as the data doesn't point to our internal buffers.
- If it's string (in PHP5 always) and in PHP6 if data is binary, then
- it still points to internal buffers and has to be copied.
- */
- if (Z_TYPE_PP(zv) == IS_STRING) {
- zval_copy_ctor(*zv);
- }
- *copy_ctor_called = TRUE;
- } else {
- /* For PS we copy stndup() the row buffers, so do nothing here */
+ If the type is IS_UNICODE, which can happen with PHP6, then we don't
+ need to copy_ctor, as the data doesn't point to our internal buffers.
+ If it's string (in PHP5 always) and in PHP6 if data is binary, then
+ it still points to internal buffers and has to be copied.
+ */
+ if (Z_TYPE_PP(zv) == IS_STRING) {
+ zval_copy_ctor(*zv);
}
+ *copy_ctor_called = TRUE;
} else {
- if (ps == FALSE) {
- /*
- Prevent Zend from freeing PS allocated data.
- Also don't null in Unicode mode as then the data doesn't point to
- the internal buffers and we will leak if we do this trick.
- */
- if (Z_TYPE_PP(zv) == IS_STRING) {
- ZVAL_NULL(*zv);
- }
- } else {
- /* For PS we copy stndup() the row buffers, so do nothing here */
+ /*
+ Prevent Zend from freeing PS allocated data.
+ Also don't null in Unicode mode as then the data doesn't point to
+ the internal buffers and we will leak if we do this trick.
+ */
+ if (Z_TYPE_PP(zv) == IS_STRING) {
+ ZVAL_NULL(*zv);
}
}
zval_ptr_dtor(zv);
Modified: trunk/mysqlnd/mysqlnd_ps.c
result = stmt->result; - result->type = MYSQLND_RES_PS; + result->type = MYSQLND_RES_PS_BUF; result->m.fetch_row = mysqlnd_fetch_stmt_row_buffered; result->m.fetch_lengths = NULL;/* makes no sense */ result->zval_cache = mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache); @@ -318,7 +318,7 @@ result->conn = stmt_to_prepare->conn->m->get_reference(stmt_to_prepare->conn);
if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn TSRMLS_CC) ||
FAIL == mysqlnd_stmt_prepare_read_eof(stmt_to_prepare TSRMLS_CC)) {
@@ -525,6 +529,9 @@
Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(current_row[i]);
stmt->result_bind[i].zv->value = current_row[i]->value;
+#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
+ zval_copy_ctor(stmt->result_bind[i].zv);
+#endif
} else {
ZVAL_NULL(stmt->result_bind[i].zv);
}
-
+#ifndef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF + zval_copy_ctor(stmt->result_bind[i].zv); +#endif if ( (Z_TYPE_P(data) == IS_STRING #if PHP_MAJOR_VERSION >= 6 @@ -671,7 +683,7 @@ MYSQLND_INC_CONN_STATISTIC(&stmt->conn->stats, STAT_PS_UNBUFFERED_SETS); result = stmt->result; - result->type = MYSQLND_RES_PS; + result->type = MYSQLND_RES_PS_UNBUF; result->m.fetch_row = stmt->cursor_exists? mysqlnd_fetch_stmt_row_cursor: mysqlnd_stmt_fetch_row_unbuffered; result->m.fetch_lengths = NULL; /* makes no sense */ @@ -757,6 +769,9 @@
if (IS_NULL != (Z_TYPE_P(stmt->result_bind[i].zv) = Z_TYPE_P(data)) ) {
stmt->result_bind[i].zv->value = data->value;
+#ifdef WE_DONT_COPY_IN_BUFFERED_AND_UNBUFFERED_BECAUSEOF_IS_REF
+ zval_copy_ctor(stmt->result_bind[i].zv);
+#endif
if ((Z_TYPE_P(data) == IS_STRING
#if PHP_MAJOR_VERSION >= 6
|| Z_TYPE_P(data) == IS_UNICODE
Modified: trunk/mysqlnd/mysqlnd_ps_codec.c
(*row) += length;
}
break;
case MYSQL_TYPE_VAR_STRING:
- /* We have already converted it to string */
+ /*
+ If the user uses refs, it could be that the type has
+ has changed and we need to convert, again. Which is noop,
+ if the type hasn't changed.
+ */
+ convert_to_string_ex(&stmt->param_bind[i].zv);
{
unsigned int len = Z_STRLEN_P(data);
/* to is after p. The latter hasn't been moved */
Modified: trunk/mysqlnd/mysqlnd_result.c
@@ -90,8 +88,7 @@
for (col = 0; col < field_count; col++) {
zend_bool copy_ctor_called;
mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache,
- result_type == MYSQLND_RES_PS,
- ©_ctor_called TSRMLS_CC);
+ result->type, ©_ctor_called TSRMLS_CC);
MYSQLND_INC_CONN_STATISTIC(NULL, copy_ctor_called? STAT_COPY_ON_WRITE_PERFORMED:
STAT_COPY_ON_WRITE_SAVED);
}
Modified: trunk/tests/ext/mysqli/009.phpt
$stmt = mysqli_prepare($link, "SELECT * FROM test_bind_fetch"); - mysqli_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7); + mysqli_bind_result($stmt, $c1, $c2, $c3, $c4, $c5, $c6, $c7, $c8); mysqli_execute($stmt); $rc = mysqli_fetch($stmt); @@ -75,7 +77,7 @@ --EXPECTF--
[0]=>
int(0)
[0]=>
int(0)
-- MySQL Code Commits Mailing List For list archives: http://lists.mysql.com/commits To unsubscribe: http://lists.mysql.com/commits?unsub=lists@pantek.comReceived on Tue Jul 17 08:36:45 2007 This archive was generated by hypermail 2.1.8 : Thu Aug 09 2007 - 19:07:16 EDT |
||||||||||
|
|||||||||||