diff options
Diffstat (limited to 'ext/mysqlnd/mysqlnd_result.c')
| -rw-r--r-- | ext/mysqlnd/mysqlnd_result.c | 83 | 
1 files changed, 53 insertions, 30 deletions
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index b997148f84..ab09530292 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -59,7 +59,6 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu  						result->stored_data->persistent,  						result->conn->options.numeric_and_datetime_as_unicode,  						result->conn->options.int_and_float_native, -						result->conn->zval_cache,  						&result->conn->stats TSRMLS_CC);  			for (i = 0; i < result->field_count; i++) {  				/* @@ -82,6 +81,53 @@ MYSQLND_METHOD(mysqlnd_res, initialize_result_set_rest)(MYSQLND_RES * const resu  /* }}} */ + +/* {{{ mysqlnd_palloc_zval_ptr_dtor */ +void mysqlnd_palloc_zval_ptr_dtor(zval **zv, enum_mysqlnd_res_type type, zend_bool * copy_ctor_called TSRMLS_DC) +{ +	DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor"); +	*copy_ctor_called = FALSE; +	{ +		/* +		  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 (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) { +			; /* do nothing, zval_ptr_dtor will do the job*/ +		} else if (Z_REFCOUNT_PP(zv) > 1) { +			/* +			  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(). + +			  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 (Z_TYPE_PP(zv) == IS_STRING) { +				ZVAL_NULL(*zv); +			} +		} +		zval_ptr_dtor(zv); +		DBG_VOID_RETURN; +	} + +	DBG_VOID_RETURN; +} +/* }}} */ + +  /* {{{ mysqlnd_res::unbuffered_free_last_data */  static void  MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRMLS_DC) @@ -102,9 +148,7 @@ MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRM  		DBG_INF_FMT("%u columns to free", result->field_count);  		for (i = 0; i < result->field_count; i++) { -			mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]), -										 result->zval_cache, result->type, -										 ©_ctor_called TSRMLS_CC); +			mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]), result->type, ©_ctor_called TSRMLS_CC);  			if (copy_ctor_called) {  				ctor_called_count++;  			} @@ -138,7 +182,6 @@ MYSQLND_METHOD(mysqlnd_res, unbuffered_free_last_data)(MYSQLND_RES * result TSRM  static void  MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES *result TSRMLS_DC)  { -	MYSQLND_THD_ZVAL_PCACHE  *zval_cache = result->zval_cache;  	MYSQLND_RES_BUFFERED *set = result->stored_data;  	unsigned int field_count = result->field_count;  	int row; @@ -157,8 +200,7 @@ MYSQLND_METHOD(mysqlnd_res, free_buffered_data)(MYSQLND_RES *result TSRMLS_DC)  			if (current_row[0] == NULL) {  				break;/* row that was never initialized */  			} -			mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache, -										 result->type, ©_ctor_called TSRMLS_CC); +			mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), result->type, ©_ctor_called TSRMLS_CC);  #if MYSQLND_DEBUG_MEMORY  			DBG_INF_FMT("Copy_ctor_called=%d", copy_ctor_called);  #endif @@ -245,12 +287,6 @@ void mysqlnd_internal_free_result_contents(MYSQLND_RES *result TSRMLS_DC)  		result->meta = NULL;  	} -	if (result->zval_cache) { -		DBG_INF("Freeing zval cache reference"); -		mysqlnd_palloc_free_thd_cache_reference(&result->zval_cache); -		result->zval_cache = NULL; -	} -  	DBG_VOID_RETURN;  }  /* }}} */ @@ -407,11 +443,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC  				/* PS has already allocated it */  				conn->field_count = rset_header.field_count;  				if (!stmt) { -					result = -						conn->current_result= -							mysqlnd_result_init(rset_header.field_count, -												mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache) -												TSRMLS_CC); +					result = conn->current_result = mysqlnd_result_init(rset_header.field_count TSRMLS_CC);  				} else {  					if (!stmt->result) {  						DBG_INF("This is 'SHOW'/'EXPLAIN'-like query."); @@ -420,11 +452,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC  						  prepared statements can't send result set metadata for these queries  						  on prepare stage. Read it now.  						*/ -						result = -							stmt->result = -								mysqlnd_result_init(rset_header.field_count, -													mysqlnd_palloc_get_thd_cache_reference(conn->zval_cache) -													TSRMLS_CC); +						result = stmt->result = mysqlnd_result_init(rset_header.field_count TSRMLS_CC);  					} else {  						/*  						  Update result set metadata if it for some reason changed between @@ -615,7 +643,6 @@ mysqlnd_fetch_row_unbuffered_c(MYSQLND_RES *result TSRMLS_DC)  								  FALSE,  								  result->conn->options.numeric_and_datetime_as_unicode,  								  result->conn->options.int_and_float_native, -								  result->conn->zval_cache,  								  &result->conn->stats TSRMLS_CC);  			retrow = mnd_malloc(result->field_count * sizeof(char *)); @@ -729,7 +756,6 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag  								  FALSE,  								  result->conn->options.numeric_and_datetime_as_unicode,  								  result->conn->options.int_and_float_native, -								  result->conn->zval_cache,  								  &result->conn->stats TSRMLS_CC);  			for (i = 0; i < field_count; i++, field++, zend_hash_key++) { @@ -884,7 +910,6 @@ mysqlnd_fetch_row_buffered_c(MYSQLND_RES *result TSRMLS_DC)  								  FALSE,  								  result->conn->options.numeric_and_datetime_as_unicode,  								  result->conn->options.int_and_float_native, -								  result->conn->zval_cache,  								  &result->conn->stats TSRMLS_CC);  			for (i = 0; i < result->field_count; i++) {  				/* @@ -954,7 +979,6 @@ mysqlnd_fetch_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,  								  result->stored_data->persistent,  								  result->conn->options.numeric_and_datetime_as_unicode,  								  result->conn->options.int_and_float_native, -								  result->conn->zval_cache,  								  &result->conn->stats TSRMLS_CC);  			for (i = 0; i < result->field_count; i++) {  				/* @@ -1511,16 +1535,15 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_data)(MYSQLND_RES *result, unsigned int  /* {{{ mysqlnd_result_init */ -MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCACHE *cache TSRMLS_DC) +MYSQLND_RES *mysqlnd_result_init(unsigned int field_count TSRMLS_DC)  {  	size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);  	MYSQLND_RES *ret = mnd_ecalloc(1, alloc_size);  	DBG_ENTER("mysqlnd_result_init"); -	DBG_INF_FMT("field_count=%u cache=%p", field_count, cache); +	DBG_INF_FMT("field_count=%u", field_count);  	ret->field_count	= field_count; -	ret->zval_cache		= cache;  	ret->m.use_result	= MYSQLND_METHOD(mysqlnd_res, use_result);  	ret->m.store_result	= MYSQLND_METHOD(mysqlnd_res, store_result);  | 
