andrey                                   Fri, 28 Aug 2009 09:30:16 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=287834

Log:
Fix for bug#48745
mysqlnd: mysql_num_fields returns wrong column count for mysql_list_fields

Bug: http://bugs.php.net/48745 (Verified) mysqlnd: mysql_num_fields returns 
wrong column count for mysql_list_fields
      
Changed paths:
    U   php/php-src/branches/PHP_5_3/NEWS
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
    U   php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result_meta.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd.h
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.h
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_debug.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_enum_n_def.h
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_palloc.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_result_meta.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_structs.h
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c
    U   php/php-src/trunk/ext/mysqlnd/php_mysqlnd.c

Modified: php/php-src/branches/PHP_5_3/NEWS
===================================================================
--- php/php-src/branches/PHP_5_3/NEWS	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/branches/PHP_5_3/NEWS	2009-08-28 09:30:16 UTC (rev 287834)
@@ -112,8 +112,10 @@
   gmail dot com, Pierre)
 - Fixed bug #48762 (IPv6 address filter still rejects valid address). (Felipe)
 - Fixed bug #48757 (ReflectionFunction::invoke() parameter issues). (Kalle)
-- Fuxed bug #48746 (Unable to browse directories within Junction Points).
+- Fixed bug #48746 (Unable to browse directories within Junction Points).
   (Pierre, Kanwaljeet Singla)
+- Fixed bug #48745 (mysqlnd: mysql_num_fields returns wrong column count for
+  mysql_list_fields). (Andrey)
 - Fixed bug #48740 (PHAR install fails when INSTALL_ROOT is not the final
   install location). (james dot cohen at digitalwindow dot com, Greg)
 - Fixed bug #48733 (CURLOPT_WRITEHEADER|CURLOPT_FILE|CURLOPT_STDERR warns on

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -431,6 +431,8 @@
 		result->m.free_result_contents(result TSRMLS_CC);
 		DBG_RETURN(FAIL);
 	}
+	/* COM_FIELD_LIST is broken and has premature EOF, thus we need to hack here and in mysqlnd_res_meta.c */
+	result->field_count = result->meta->field_count;

 	/*
 	  2. Follows an EOF packet, which the client of mysqlnd_read_result_metadata()

Modified: php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result_meta.c
===================================================================
--- php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result_meta.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/branches/PHP_5_3/ext/mysqlnd/mysqlnd_result_meta.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -166,6 +166,7 @@
 			DBG_RETURN(FAIL);
 		}
 		if (field_packet.stupid_list_fields_eof == TRUE) {
+			meta->field_count = i + 1;
 			break;
 		}


Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd.h
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd.h	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd.h	2009-08-28 09:30:16 UTC (rev 287834)
@@ -17,19 +17,17 @@
   |          Ulf Wendel <uwen...@mysql.com>                              |
   +----------------------------------------------------------------------+
 */
-
 /* $Id$ */

 #ifndef MYSQLND_H
 #define MYSQLND_H

-#define MYSQLND_VERSION "mysqlnd/PHP " PHP_VERSION " $Revision$"
-#define MYSQLND_VERSION_ID PHP_VERSION_ID
+#define MYSQLND_VERSION "mysqlnd 5.0.5-dev - 081106 - $Revision$"
+#define MYSQLND_VERSION_ID 50005

 /* This forces inlining of some accessor functions */
 #define MYSQLND_USE_OPTIMISATIONS 1

-
 #define MYSQLND_STRING_TO_INT_CONVERSION
 /*
   This force mysqlnd to do a single (or more depending on ammount of data)
@@ -318,9 +316,11 @@
 PHPAPI void						 _mysqlnd_palloc_rshutdown(MYSQLND_THD_ZVAL_PCACHE * cache TSRMLS_DC);


+#define mysqlnd_palloc_init_thd_cache(cache) 			_mysqlnd_palloc_init_thd_cache((cache) TSRMLS_CC)
 #define mysqlnd_palloc_free_thd_cache_reference(cache)	_mysqlnd_palloc_free_thd_cache_reference((cache) TSRMLS_CC)
 #define mysqlnd_palloc_get_thd_cache_reference(cache)	_mysqlnd_palloc_get_thd_cache_reference((cache) TSRMLS_CC)

+PHPAPI MYSQLND_THD_ZVAL_PCACHE*	_mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC);
 MYSQLND_THD_ZVAL_PCACHE*		_mysqlnd_palloc_get_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE * const cache TSRMLS_DC);
 PHPAPI void						_mysqlnd_palloc_free_thd_cache_reference(MYSQLND_THD_ZVAL_PCACHE **cache TSRMLS_DC);


Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -35,7 +35,7 @@
 	DBG_ENTER("mysqlnd_mempool_dtor");
 	for (i = 0; i < pool->free_chunk_list_elements; i++) {
 		MYSQLND_MEMORY_POOL_CHUNK * chunk = pool->free_chunk_list[i];
-		mysqlnd_mempool_free_chunk(chunk, FALSE TSRMLS_CC);
+		chunk->free_chunk(chunk, FALSE TSRMLS_CC);
 	}

 	DBG_VOID_RETURN;
@@ -44,14 +44,11 @@


 /* {{{ mysqlnd_mempool_free_chunk */
-void
+static void
 mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, zend_bool cache_it TSRMLS_DC)
 {
 	MYSQLND_MEMORY_POOL * pool = chunk->pool;
 	DBG_ENTER("mysqlnd_mempool_free_chunk");
-	if (!chunk) {
-		DBG_VOID_RETURN;
-	}
 	if (chunk->from_pool) {
 		/* Try to back-off and guess if this is the last block allocated */
 		if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) {
@@ -78,7 +75,7 @@


 /* {{{ mysqlnd_mempool_resize_chunk */
-void
+static void
 mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size TSRMLS_DC)
 {
 	DBG_ENTER("mysqlnd_mempool_resize_chunk");
@@ -138,6 +135,8 @@
 		chunk = mnd_malloc(sizeof(MYSQLND_MEMORY_POOL_CHUNK));
 	}

+	chunk->free_chunk = mysqlnd_mempool_free_chunk;
+	chunk->resize_chunk = mysqlnd_mempool_resize_chunk;
 	chunk->size = size;
 	/*
 	  Should not go over MYSQLND_MAX_PACKET_SIZE, since we
@@ -184,12 +183,10 @@
 mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool TSRMLS_DC)
 {
 	DBG_ENTER("mysqlnd_mempool_destroy");
-	if (pool) {
-		/* mnd_free will reference LOCK_access and might crash, depending on the caller...*/
-		mysqlnd_mempool_free_contents(pool TSRMLS_CC);
-		mnd_free(pool->arena);
-		mnd_free(pool);
-	}
+	/* mnd_free will reference LOCK_access and might crash, depending on the caller...*/
+	mysqlnd_mempool_free_contents(pool TSRMLS_CC);
+	mnd_free(pool->arena);
+	mnd_free(pool);
 	DBG_VOID_RETURN;
 }
 /* }}} */

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.h
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.h	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_block_alloc.h	2009-08-28 09:30:16 UTC (rev 287834)
@@ -25,10 +25,7 @@

 MYSQLND_MEMORY_POOL *	mysqlnd_mempool_create(size_t arena_size TSRMLS_DC);
 void 					mysqlnd_mempool_destroy(MYSQLND_MEMORY_POOL * pool TSRMLS_DC);
-void					mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size TSRMLS_DC);
-void					mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, zend_bool cache_it TSRMLS_DC);

-
 #endif	/* MYSQLND_BLOCK_ALLOC_H */



Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_debug.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_debug.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_debug.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -830,9 +830,6 @@
 void _mysqlnd_efree(void *ptr MYSQLND_MEM_D)
 {
 	DBG_ENTER(mysqlnd_efree_name);
-	if (!ptr) {
-		DBG_VOID_RETURN;
-	}
 #ifdef MYSQLND_THREADED
 	if (MYSQLND_G(thread_id) != tsrm_thread_id()) {
 		DBG_RETURN(_mysqlnd_pefree(ptr, 1 TSRMLS_CC ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC));

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_enum_n_def.h
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_enum_n_def.h	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_enum_n_def.h	2009-08-28 09:30:16 UTC (rev 287834)
@@ -142,6 +142,7 @@
 	MYSQLND_OPT_NET_READ_BUFFER_SIZE = 203,
 } enum_mysqlnd_option;

+
 typedef enum mysqlnd_field_types
 {
 	MYSQL_TYPE_DECIMAL,
@@ -176,6 +177,7 @@
 /* Please update this if there is a new type after MYSQL_TYPE_GEOMETRY */
 #define MYSQL_TYPE_LAST		MYSQL_TYPE_GEOMETRY

+
 typedef enum mysqlnd_server_option
 {
 	MYSQL_OPTION_MULTI_STATEMENTS_ON,
@@ -239,6 +241,7 @@
 /* see mysqlnd_charset.c for more information */
 #define MYSQLND_BINARY_CHARSET_NR	63

+
 /*
           /-----> CONN_CLOSE  <---------------\
          |           ^                         \
@@ -258,6 +261,7 @@
 	CONN_QUIT_SENT, /* object is "destroyed" at this stage */
 } enum_mysqlnd_connection_state;

+
 typedef enum mysqlnd_stmt_state
 {
 	MYSQLND_STMT_INITTED = 0,
@@ -268,11 +272,13 @@
 	MYSQLND_STMT_USER_FETCHING, /* fetch_row_buff or fetch_row_unbuf */
 } enum_mysqlnd_stmt_state;

+
 typedef enum param_bind_flags
 {
 	MYSQLND_PARAM_BIND_BLOB_USED = 1
 } enum_param_bind_flags;

+
 /* PS */
 enum mysqlnd_stmt_attr
 {
@@ -280,6 +286,7 @@
 	STMT_ATTR_CURSOR_TYPE,
 	STMT_ATTR_PREFETCH_ROWS
 };
+
 enum myslqnd_cursor_type
 {
 	CURSOR_TYPE_NO_CURSOR= 0,
@@ -287,6 +294,7 @@
 	CURSOR_TYPE_FOR_UPDATE= 2,
 	CURSOR_TYPE_SCROLLABLE= 4
 };
+
 typedef enum mysqlnd_connection_close_type
 {
 	MYSQLND_CLOSE_EXPLICIT = 0,
@@ -295,6 +303,7 @@
 	MYSQLND_CLOSE_LAST	/* for checking, should always be last */
 } enum_connection_close_type;

+
 typedef enum mysqlnd_collected_stats
 {
 	STAT_BYTES_SENT,

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_palloc.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_palloc.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_palloc.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -82,7 +82,6 @@


 /* {{{ mysqlnd_palloc_get_cache_reference */
-static inline
 MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_get_cache_reference(MYSQLND_ZVAL_PCACHE * const cache)
 {
 	if (cache) {
@@ -95,20 +94,6 @@
 /* }}} */


-/* {{{ mysqlnd_palloc_release_cache_reference */
-static inline
-MYSQLND_ZVAL_PCACHE* mysqlnd_palloc_release_cache_reference(MYSQLND_ZVAL_PCACHE * const cache)
-{
-	if (cache) {
-		LOCK_PCACHE(cache);
-		cache->references--;
-		UNLOCK_PCACHE(cache);
-	}
-	return cache;
-}
-/* }}} */
-
-
 /* {{{ mysqlnd_palloc_free_cache */
 /*
   As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
@@ -137,9 +122,9 @@


 /* {{{ _mysqlnd_palloc_init_thd_cache */
-MYSQLND_THD_ZVAL_PCACHE* mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC)
+PHPAPI MYSQLND_THD_ZVAL_PCACHE* _mysqlnd_palloc_init_thd_cache(MYSQLND_ZVAL_PCACHE * const cache TSRMLS_DC)
 {
-	MYSQLND_THD_ZVAL_PCACHE *ret = mnd_ecalloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE));
+	MYSQLND_THD_ZVAL_PCACHE *ret = calloc(1, sizeof(MYSQLND_THD_ZVAL_PCACHE));
 	DBG_ENTER("_mysqlnd_palloc_init_thd_cache");
 	DBG_INF_FMT("ret = %p", ret);

@@ -161,7 +146,7 @@
 	ret->references = 1;

 	/* 1. Initialize the GC list */
-	ret->gc_list.ptr_line = mnd_ecalloc(cache->max_items, sizeof(mysqlnd_zval *));
+	ret->gc_list.ptr_line = calloc(cache->max_items, sizeof(mysqlnd_zval *));
 	/* Backward and forward looping is possible */
 	ret->gc_list.last_added = ret->gc_list.ptr_line;
 	ret->gc_list.canary1 = (void*)0xCAFE;
@@ -178,18 +163,17 @@
 {
 	DBG_ENTER("_mysqlnd_palloc_get_thd_cache_reference");
 	if (cache) {
+		++cache->references;
 		DBG_INF_FMT("cache=%p new_refc=%d gc_list.canary1=%p gc_list.canary2=%p",
 					cache, cache->references, cache->gc_list.canary1, cache->gc_list.canary2);
 		mysqlnd_palloc_get_cache_reference(cache->parent);
-		/* No concurrency here, we are in the same thread */
-		++cache->references;
 	}
 	DBG_RETURN(cache);
 }
 /* }}} */


-/* {{{ mysqlnd_palloc_free_thd_cache */
+/* {{{ mysqlnd_palloc_free_cache */
 /*
   As this call will happen on MSHUTDOWN(), then we don't need to copy the zvals with
   copy_ctor but scrap what they point to with zval_dtor() and then just free our
@@ -233,8 +217,8 @@
 		UNLOCK_PCACHE(global_cache);

 	}
-	mnd_efree(thd_cache->gc_list.ptr_line);
-	mnd_efree(thd_cache);
+	mnd_free(thd_cache->gc_list.ptr_line);
+	mnd_free(thd_cache);

 	DBG_VOID_RETURN;
 }
@@ -246,7 +230,7 @@
 {
 	DBG_ENTER("_mysqlnd_palloc_free_thd_cache_reference");
 	if (*cache) {
-		mysqlnd_palloc_release_cache_reference((*cache)->parent);
+		--(*cache)->parent->references;
 		DBG_INF_FMT("cache=%p references_left=%d canary1=%p canary2=%p",
 					*cache, (*cache)->references, (*cache)->gc_list.canary1, (*cache)->gc_list.canary2);

@@ -413,9 +397,6 @@
 {
 	MYSQLND_ZVAL_PCACHE *cache;
 	DBG_ENTER("mysqlnd_palloc_zval_ptr_dtor");
-	if (!*zv) {
-		DBG_VOID_RETURN;
-	}
 	if (thd_cache) {
 		DBG_INF_FMT("cache=%p parent_block=%p last_in_block=%p *zv=%p refc=%d type=%d ",
 					thd_cache,
@@ -547,7 +528,7 @@
 /* {{{ _mysqlnd_palloc_rinit */
 PHPAPI MYSQLND_THD_ZVAL_PCACHE * _mysqlnd_palloc_rinit(MYSQLND_ZVAL_PCACHE * cache TSRMLS_DC)
 {
-	return mysqlnd_palloc_init_thd_cache(cache TSRMLS_CC);
+	return mysqlnd_palloc_init_thd_cache(cache);
 }
 /* }}} */


Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_ps.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -871,7 +871,7 @@
 							result->meta->fields[i].max_length = Z_STRLEN_P(data);
 						}
 						stmt->result_bind[i].zv->value = data->value;
-						/* copied data, thus also the ownership. Thus null data */
+						// copied data, thus also the ownership. Thus null data
 						ZVAL_NULL(data);
 					}
 				}
@@ -885,7 +885,7 @@
 			  the bound variables. Thus we need to do part of what it does or Zend will
 			  report leaks.
 			*/
-			mysqlnd_mempool_free_chunk(row_packet->row_buffer, TRUE TSRMLS_CC);
+			row_packet->row_buffer->free_chunk(row_packet->row_buffer, TRUE TSRMLS_CC);
 			row_packet->row_buffer = NULL;
 		}
 	} else if (ret == FAIL) {
@@ -1047,7 +1047,7 @@
 							result->meta->fields[i].max_length = Z_STRLEN_P(data);
 						}
 						stmt->result_bind[i].zv->value = data->value;
-						/* copied data, thus also the ownership. Thus null data */
+						// copied data, thus also the ownership. Thus null data
 						ZVAL_NULL(data);
 					}
 				}
@@ -1060,13 +1060,13 @@
 			  the bound variables. Thus we need to do part of what it does or Zend will
 			  report leaks.
 			*/
-			mysqlnd_mempool_free_chunk(row_packet->row_buffer, TRUE TSRMLS_CC);
+			row_packet->row_buffer->free_chunk(row_packet->row_buffer, TRUE TSRMLS_CC);
 			row_packet->row_buffer = NULL;
 		}
 		/* We asked for one row, the next one should be EOF, eat it */
 		ret = PACKET_READ(row_packet, result->conn);
 		if (row_packet->row_buffer) {
-			mysqlnd_mempool_free_chunk(row_packet->row_buffer, TRUE TSRMLS_CC);
+			row_packet->row_buffer->free_chunk(row_packet->row_buffer, TRUE TSRMLS_CC);
 			row_packet->row_buffer = NULL;
 		}
 		MYSQLND_INC_CONN_STATISTIC(&stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR);

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_result.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -30,9 +30,6 @@
 #include "mysqlnd_debug.h"
 #include "ext/standard/basic_functions.h"

-#define START_FREEING_AFTER_X_ROWS 10
-static void mysqlnd_buffered_free_previous_row(MYSQLND_RES *result, int which TSRMLS_DC);
-
 #define MYSQLND_SILENT

 #ifdef MYSQLND_THREADED
@@ -104,18 +101,11 @@
 	unsigned int field_count = result->meta->field_count;
 	unsigned int row_count = result->stored_data->row_count;
 	DBG_ENTER("mysqlnd_res_initialize_result_set_rest");
-	DBG_INF_FMT("before heap=%lu real=%lu", zend_memory_usage(FALSE TSRMLS_CC), zend_memory_usage(TRUE TSRMLS_CC));

 	if (!data_cursor || row_count == result->stored_data->initialized_rows) {
 		DBG_VOID_RETURN;
 	}
 	while ((data_cursor - data_begin) < (row_count * field_count)) {
-		if (START_FREEING_AFTER_X_ROWS < ((data_cursor - data_begin) / result->field_count)) {
-			zval **orig_data_cursor = result->stored_data->data_cursor;
-			result->stored_data->data_cursor = data_cursor;
-			mysqlnd_buffered_free_previous_row(result, START_FREEING_AFTER_X_ROWS TSRMLS_CC);
-			result->stored_data->data_cursor = orig_data_cursor;
-		}
 		if (NULL == data_cursor[0]) {
 			result->stored_data->initialized_rows++;
 			result->m.row_decoder(
@@ -140,7 +130,6 @@
 		}
 		data_cursor += field_count;
 	}
-	DBG_INF_FMT("after heap=%lu real=%lu", zend_memory_usage(FALSE TSRMLS_CC), zend_memory_usage(TRUE TSRMLS_CC));
 	DBG_VOID_RETURN;
 }
 /* }}} */
@@ -188,7 +177,7 @@
 	if (unbuf->last_row_buffer) {
 		DBG_INF("Freeing last row buffer");
 		/* Nothing points to this buffer now, free it */
-		mysqlnd_mempool_free_chunk(unbuf->last_row_buffer, TRUE TSRMLS_CC);
+		unbuf->last_row_buffer->free_chunk(unbuf->last_row_buffer, TRUE TSRMLS_CC);
 		unbuf->last_row_buffer = NULL;
 	}

@@ -197,53 +186,6 @@
 /* }}} */


-/* {{{ mysqlnd_buffered_free_previous_row */
-static
-void mysqlnd_buffered_free_previous_row(MYSQLND_RES *result, int which TSRMLS_DC)
-{
-	MYSQLND_RES_BUFFERED * set = result->stored_data;
-
-	DBG_ENTER("mysqlnd_buffered_free_previous_row");
-
-	if (!set) {
-		DBG_VOID_RETURN;
-	}
-
-	DBG_INF_FMT("which=%d result->field_count=%d data=%p data_cursor=%p", which, result->field_count, set->data, set->data_cursor);
-	if (set->data_cursor && ((set->data_cursor - (which * result->field_count) ) >= set->data)) {
-		unsigned int i, ctor_called_count = 0;
-		zend_bool copy_ctor_called;
-		MYSQLND_STATS *global_stats = result->conn? &result->conn->stats:NULL;
-		zval **current_row = set->data_cursor - (which * result->field_count);
-
-		DBG_INF_FMT("%u columns to free", result->field_count);
-		for (i = 0; i < result->field_count; i++) {
-			if (current_row[i]) {
-				mysqlnd_palloc_zval_ptr_dtor(&(current_row[i]),
-											 result->zval_cache, result->type,
-											 &copy_ctor_called TSRMLS_CC);
-				if (copy_ctor_called) {
-					ctor_called_count++;
-				}
-				current_row[i] = NULL;
-			}
-		}
-		DBG_INF_FMT("copy_ctor_called_count=%u", ctor_called_count);
-		/* By using value3 macros we hold a mutex only once, there is no value2 */
-		MYSQLND_INC_CONN_STATISTIC_W_VALUE3(global_stats,
-											STAT_COPY_ON_WRITE_PERFORMED,
-											ctor_called_count,
-											STAT_COPY_ON_WRITE_SAVED,
-											result->field_count - ctor_called_count,
-											STAT_COPY_ON_WRITE_PERFORMED, 0);
-	}
-
-	DBG_VOID_RETURN;
-}
-/* }}} */
-
-
-
 /* {{{ mysqlnd_free_buffered_data */
 void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
 {
@@ -263,20 +205,21 @@

 		for (col = field_count - 1; col >= 0; --col) {
 			zend_bool copy_ctor_called;
-			if (current_row[col] != NULL) {
-				mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache,
+			if (current_row[0] == NULL) {
+				break;/* row that was never initialized */
+			}
+			mysqlnd_palloc_zval_ptr_dtor(&(current_row[col]), zval_cache,
 										 result->type, &copy_ctor_called TSRMLS_CC);
 #if MYSQLND_DEBUG_MEMORY
-				DBG_INF_FMT("Copy_ctor_called=%d", copy_ctor_called);
+			DBG_INF_FMT("Copy_ctor_called=%d", copy_ctor_called);
 #endif
-				MYSQLND_INC_GLOBAL_STATISTIC(copy_ctor_called? STAT_COPY_ON_WRITE_PERFORMED:
-															   STAT_COPY_ON_WRITE_SAVED);
-			}
+			MYSQLND_INC_GLOBAL_STATISTIC(copy_ctor_called? STAT_COPY_ON_WRITE_PERFORMED:
+														   STAT_COPY_ON_WRITE_SAVED);
 		}
 #if MYSQLND_DEBUG_MEMORY
 		DBG_INF("Freeing current_row & current_buffer");
 #endif
-		mysqlnd_mempool_free_chunk(current_buffer, TRUE TSRMLS_CC);
+		current_buffer->free_chunk(current_buffer, TRUE TSRMLS_CC);
 	}
 	DBG_INF("Freeing data & row_buffer");
 	if (set->data) {
@@ -354,7 +297,7 @@
 #endif
 			pefree(current_row, set->persistent);
 		}
-		mysqlnd_mempool_free_chunk(current_buffer, TRUE TSRMLS_CC);
+		current_buffer->free_chunk(current_buffer, TRUE TSRMLS_CC);
 	}
 	DBG_INF("Freeing data & row_buffer");
 	pefree(set->data, set->persistent);
@@ -488,6 +431,8 @@
 		result->m.free_result_contents(result TSRMLS_CC);
 		DBG_RETURN(FAIL);
 	}
+	/* COM_FIELD_LIST is broken and has premature EOF, thus we need to hack here and in mysqlnd_res_meta.c */
+	result->field_count = result->meta->field_count;

 	/*
 	  2. Follows an EOF packet, which the client of mysqlnd_read_result_metadata()
@@ -1156,10 +1101,6 @@
 		zval **current_row = set->data_cursor;
 		MYSQLND_FIELD *field = result->meta->fields;
 		struct mysqlnd_field_hash_key *zend_hash_key = result->meta->zend_hash_keys;
-		DBG_INF_FMT("row_num=%u", (set->data_cursor - set->data) / result->meta->field_count);
-		if (START_FREEING_AFTER_X_ROWS < ((set->data_cursor - set->data) / result->field_count)) {
-			mysqlnd_buffered_free_previous_row(result, START_FREEING_AFTER_X_ROWS TSRMLS_CC);
-		}

 		if (NULL == current_row[0]) {
 			uint64_t row_num = (set->data_cursor - set->data) / result->meta->field_count;
@@ -1909,7 +1850,6 @@

 	DBG_ENTER("mysqlnd_res::fetch_into");
 	DBG_INF_FMT("flags=%u mysqlnd_extension=%d", flags, extension);
-	DBG_INF_FMT("memory in use: heap_size=%lu real_size=%u", zend_memory_usage(FALSE TSRMLS_CC), zend_memory_usage(TRUE TSRMLS_CC));

 	if (!result->m.fetch_row) {
 		RETVAL_NULL();
@@ -1921,7 +1861,7 @@
 	*/
 	mysqlnd_array_init(return_value, mysqlnd_num_fields(result) * 2);
 	if (FAIL == result->m.fetch_row(result, (void *)return_value, flags, &fetched_anything TSRMLS_CC)) {
-		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading/decoding a row");
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error while reading a row");
 		RETVAL_FALSE;
 	} else if (fetched_anything == FALSE) {
 		zval_dtor(return_value);
@@ -1939,7 +1879,6 @@
 	  return_value is IS_NULL for no more data and an array for data. Thus it's ok
 	  to return here.
 	*/
-	DBG_INF_FMT("returning: heap_size=%lu real_size=%u", zend_memory_usage(FALSE TSRMLS_CC), zend_memory_usage(TRUE TSRMLS_CC));
 	DBG_VOID_RETURN;
 }
 /* }}} */

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_result_meta.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_result_meta.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_result_meta.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -166,6 +166,7 @@
 			DBG_RETURN(FAIL);
 		}
 		if (field_packet.stupid_list_fields_eof == TRUE) {
+			meta->field_count = i + 1;
 			break;
 		}


Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_structs.h
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_structs.h	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_structs.h	2009-08-28 09:30:16 UTC (rev 287834)
@@ -45,10 +45,12 @@

 struct st_mysqlnd_memory_pool_chunk
 {
-	uint32_t			app;
+	uint64_t			app;
 	MYSQLND_MEMORY_POOL *pool;
 	zend_uchar			*ptr;
-	uint32_t			size;
+	unsigned int				size;
+	void				(*resize_chunk)(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size TSRMLS_DC);
+	void				(*free_chunk)(MYSQLND_MEMORY_POOL_CHUNK * chunk, zend_bool cache_it TSRMLS_DC);
 	zend_bool			from_pool;
 };


Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -43,6 +43,7 @@
 #define MYSQLND_DUMP_HEADER_N_BODY2
 #define MYSQLND_DUMP_HEADER_N_BODY_FULL2

+
 #define	PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_size, packet_type_as_text, packet_type) \
 	{ \
 		if (FAIL == mysqlnd_read_header((conn), &((packet)->header) TSRMLS_CC)) {\
@@ -70,6 +71,7 @@
 											1); \
 	}

+
 extern mysqlnd_packet_methods packet_methods[];

 static const char *unknown_sqlstate= "HY000";
@@ -611,7 +613,7 @@
 	/* pad2 */
 	p+= 13;

-	if ((size_t)(p - buf) < packet->header.size) {
+	if (p - buf < packet->header.size) {
 		/* scramble_buf is split into two parts */
 		memcpy(packet->scramble_buf + SCRAMBLE_LENGTH_323,
 				p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
@@ -625,7 +627,7 @@
 	DBG_INF_FMT("server_capabilities=%d charset_no=%d server_status=%d",
 				packet->server_capabilities, packet->charset_no, packet->server_status);

-	if ((size_t)(p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("GREET packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "GREET packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
 						 p - begin - packet->header.size);
@@ -810,7 +812,7 @@
 	p+= 2;

 	/* There is a message */
-	if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
+	if (packet->header.size > p - buf && (i = php_mysqlnd_net_field_length(&p))) {
 		packet->message = pestrndup((char *)p, MIN(i, sizeof(buf) - (p - buf)), conn->persistent);
 		packet->message_len = i;
 	} else {
@@ -821,7 +823,7 @@
 				packet->affected_rows, packet->last_insert_id, packet->server_status,
 				packet->warning_count);

-	if ((size_t)(p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("OK packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "OK packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
 						 p - begin - packet->header.size);
@@ -894,7 +896,7 @@
 		packet->server_status = 0;
 	}

-	if ((size_t)(p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("EOF packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "EOF packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
 						 p - begin - packet->header.size);
@@ -1044,7 +1046,7 @@
 			packet->warning_count = uint2korr(p);
 			p+=2;
 			/* Check for additional textual data */
-			if (packet->header.size  > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) {
+			if (packet->header.size  > (p - buf) && (len = php_mysqlnd_net_field_length(&p))) {
 				packet->info_or_local_file = mnd_pemalloc(len + 1, conn->persistent);
 				memcpy(packet->info_or_local_file, p, len);
 				packet->info_or_local_file[len] = '\0';
@@ -1059,7 +1061,7 @@
 			/* Result set */
 			break;
 	}
-	if ((size_t)(p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("RSET_HEADER packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "GREET packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
 						 p - begin - packet->header.size);
@@ -1187,7 +1189,7 @@
 	  NULL_LENGTH (0xFB) comes from COM_FIELD_LIST when the default value is NULL.
 	  Otherwise the string is length encoded.
 	*/
-	if (packet->header.size > (size_t)(p - buf) &&
+	if (packet->header.size > (p - buf) &&
 		(len = php_mysqlnd_net_field_length(&p)) &&
 		len != MYSQLND_NULL_LENGTH)
 	{
@@ -1199,7 +1201,7 @@
 		p += len;
 	}

-	if ((size_t)(p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("RSET field packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Result set field packet "MYSQLND_SZ_T_SPEC" bytes "
 				 		"shorter than expected", p - begin - packet->header.size);
@@ -1327,7 +1329,7 @@
 			  We need a trailing \0 for the last string, in case of text-mode,
 			  to be able to implement read-only variables.
 			*/
-			mysqlnd_mempool_resize_chunk((*buffer), *data_size + 1 TSRMLS_CC);
+			(*buffer)->resize_chunk((*buffer), *data_size + 1 TSRMLS_CC);
 			/* The position could have changed, recalculate */
 			p = (*buffer)->ptr + (*data_size - header.size);
 		}
@@ -1343,8 +1345,8 @@
 			break;
 		}
 	}
-	if (ret == FAIL && (*buffer)) {
-		mysqlnd_mempool_free_chunk(*buffer, TRUE TSRMLS_CC);
+	if (ret == FAIL) {
+		(*buffer)->free_chunk((*buffer), TRUE TSRMLS_CC);
 		*buffer = NULL;
 	}
 	*data_size -= prealloc_more_bytes;
@@ -1362,10 +1364,8 @@
 	zend_uchar *null_ptr, bit;
 	zval **current_field, **end_field, **start_field;
 	zend_bool as_unicode = conn->options.numeric_and_datetime_as_unicode;
-#ifdef USE_ZVAL_CACHE
 	zend_bool allocated;
-	void *obj = NULL;
-#endif
+	void *obj;

 	DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");

@@ -1827,7 +1827,7 @@
 	DBG_ENTER("php_mysqlnd_rowp_free_mem");
 	p = (php_mysql_packet_row *) _packet;
 	if (p->row_buffer) {
-		mysqlnd_mempool_free_chunk(p->row_buffer, TRUE TSRMLS_CC);
+		p->row_buffer->free_chunk(p->row_buffer, TRUE TSRMLS_CC);
 		p->row_buffer = NULL;
 	}
 	DBG_INF_FMT("alloca=%d persistent=%d", (int)alloca, (int)p->header.persistent);
@@ -1945,7 +1945,7 @@
 	DBG_INF_FMT("Prepare packet read: stmt_id=%d fields=%d params=%d",
 				packet->stmt_id, packet->field_count, packet->param_count);

-	if ((size_t) (p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("PREPARE packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "PREPARE packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
 						 p - begin - packet->header.size);
@@ -2005,7 +2005,7 @@
 										 packet->error_info.sqlstate
 										 TSRMLS_CC);
 	}
-	if ((size_t)(p - begin) > packet->header.size) {
+	if (p - begin > packet->header.size) {
 		DBG_ERR_FMT("CHANGE_USER packet %d bytes shorter than expected", p - begin - packet->header.size);
 		php_error_docref(NULL TSRMLS_CC, E_WARNING, "CHANGE_USER packet "MYSQLND_SZ_T_SPEC" bytes shorter than expected",
 						 p - begin - packet->header.size);

Modified: php/php-src/trunk/ext/mysqlnd/php_mysqlnd.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/php_mysqlnd.c	2009-08-28 09:25:40 UTC (rev 287833)
+++ php/php-src/trunk/ext/mysqlnd/php_mysqlnd.c	2009-08-28 09:30:16 UTC (rev 287834)
@@ -46,13 +46,13 @@

 	zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(values), &pos_values);
 	while (zend_hash_get_current_data_ex(Z_ARRVAL_P(values),
-		(void **)&values_entry, &pos_values) == SUCCESS) {
+										(void **)&values_entry, &pos_values) == SUCCESS) {
+		TSRMLS_FETCH();
 		zstr	string_key;
 		uint	string_key_len;
 		ulong	num_key;
 		int     s_len;
 		char 	*s = NULL;
-		TSRMLS_FETCH();

 		zend_hash_get_current_key_ex(Z_ARRVAL_P(values), &string_key, &string_key_len, &num_key, 0, &pos_values);

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to