List:Commits« Previous MessageNext Message »
From:ahristov Date:March 21 2007 8:07pm
Subject:PHP mysqlnd svn commit: r243 - in trunk/ext/mysqli: . mysqlnd
View as plain text  
Author: ahristov
Date: 2007-03-21 20:07:06 +0100 (Wed, 21 Mar 2007)
New Revision: 243

Modified:
   trunk/ext/mysqli/config.m4
   trunk/ext/mysqli/mysqli_api.c
   trunk/ext/mysqli/mysqli_mysqlnd.h
   trunk/ext/mysqli/mysqlnd/mysqlnd.c
   trunk/ext/mysqli/mysqlnd/mysqlnd.h
   trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c
Log:
Refactor mysqlnd, separate, really, the buffered
from unbuffered sets. A step forward to be able to
preserve (cache) buffered sets.


Modified: trunk/ext/mysqli/config.m4
===================================================================
--- trunk/ext/mysqli/config.m4	2007-03-21 15:24:52 UTC (rev 242)
+++ trunk/ext/mysqli/config.m4	2007-03-21 19:07:06 UTC (rev 243)
@@ -16,7 +16,7 @@
 
   AC_DEFINE(HAVE_MYSQLND, 1, "MySQL native driver support enabled")
   extra_sources="mysqlnd/mysqlnd.c mysqlnd/mysqlnd_charset.c
mysqlnd/mysqlnd_wireprotocol.c \
-                  mysqlnd/mysqlnd_ps.c mysqlnd/mysqlnd_loaddata.c mysqlnd/mysqlnd_alloc.c
mysqlnd/mysqlnd_palloc.c \
+                  mysqlnd/mysqlnd_ps.c mysqlnd/mysqlnd_loaddata.c
mysqlnd/mysqlnd_palloc.c \
 				  mysqlnd/mysqlnd_ps_codec.c mysqlnd/mysqlnd_statistics.c mysqlnd/mysqlnd_qcache.c"
 
 elif test "$PHP_MYSQLI" != "no"; then

Modified: trunk/ext/mysqli/mysqli_api.c
===================================================================
--- trunk/ext/mysqli/mysqli_api.c	2007-03-21 15:24:52 UTC (rev 242)
+++ trunk/ext/mysqli/mysqli_api.c	2007-03-21 19:07:06 UTC (rev 243)
@@ -607,7 +607,7 @@
 		RETURN_FALSE;
 	}
 
-	if (offset < 0 || offset >= result->row_count) {
+	if (offset < 0 || offset >= mysql_num_rows(result)) {
 	   RETURN_FALSE;
 	}
 

Modified: trunk/ext/mysqli/mysqli_mysqlnd.h
===================================================================
--- trunk/ext/mysqli/mysqli_mysqlnd.h	2007-03-21 15:24:52 UTC (rev 242)
+++ trunk/ext/mysqli/mysqli_mysqlnd.h	2007-03-21 19:07:06 UTC (rev 243)
@@ -112,7 +112,7 @@
 #define MYSQLI_CLOSE_IMPLICIT			MYSQLND_CLOSE_IMPLICIT
 #define MYSQLI_CLOSE_DISCONNECTED		MYSQLND_CLOSE_DISCONNECTED
 
-#define mysqli_result_is_unbuffered(r)	((r)->conn)
+#define mysqli_result_is_unbuffered(r)	((r)->unbuf)
 #define mysqli_server_status(c)			(c)->upsert_status.server_status
 #define mysqli_stmt_warning_count(s)	mysqlnd_stmt_warning_count((s))
 #define mysqli_stmt_server_status(s)	(s)->upsert_status.server_status

Modified: trunk/ext/mysqli/mysqlnd/mysqlnd.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd.c	2007-03-21 15:24:52 UTC (rev 242)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd.c	2007-03-21 19:07:06 UTC (rev 243)
@@ -114,15 +114,20 @@
 /* {{{ mysqlnd_unbuffered_free_last_data */
 void mysqlnd_unbuffered_free_last_data(MYSQLND_RES *result TSRMLS_DC)
 {
-	if (result->last_row_data) {
+	MYSQLND_RES_UNBUFFERED *unbuf = result->unbuf;
+	if (!unbuf) {
+		return;
+	}
+
+	if (unbuf->last_row_data) {
 		int i;
 		zend_bool copy_ctor_called;
 		for (i = 0; i < result->field_count; i++) {
 			if (result->type == MYSQLND_RES_PS) {
 				/* Do nothing, before assigning we will clean */
-				zval_ptr_dtor(&result->last_row_data[i]);
+				zval_ptr_dtor(&unbuf->last_row_data[i]);
 			} else {
-				mysqlnd_palloc_zval_ptr_dtor(&(result->last_row_data[i]),
+				mysqlnd_palloc_zval_ptr_dtor(&(unbuf->last_row_data[i]),
 											 result->zval_cache, FALSE,
 											 &copy_ctor_called TSRMLS_CC);
 				if (copy_ctor_called) {
@@ -136,13 +141,13 @@
 			}
 		}
 		/* Free last row's zvals */
-		efree(result->last_row_data);
-		result->last_row_data = NULL;
+		efree(unbuf->last_row_data);
+		unbuf->last_row_data = NULL;
 	}
-	if (result->last_row_buffer) {
+	if (unbuf->last_row_buffer) {
 		/* Nothing points to this buffer now, free it */
-		efree(result->last_row_buffer);
-		result->last_row_buffer = NULL;
+		efree(unbuf->last_row_buffer);
+		unbuf->last_row_buffer = NULL;
 	}
 }
 /* }}} */
@@ -152,22 +157,22 @@
 void mysqlnd_internal_free_result_buffers(MYSQLND_RES *result TSRMLS_DC)
 {
 	int i;
-	/* The user has used the old API - mysqlnd_fetch_row() */
-	if (result->last_row) {
-		efree(result->last_row);
-		result->last_row = NULL;
-	}
 
 	if (!result->data) {
 		mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
+		if (result->unbuf) {
+			efree(result->unbuf);
+			result->unbuf = NULL;
+		}
 	} else {
 		zval **current_row;
 		zend_uchar *current_buffer;
+		MYSQLND_RES_BUFFERED *set = result->data;
 		int j;
 
-		for (i = 0; i < result->row_count; i++) {
-			current_row = result->data[i];
-			current_buffer = result->row_buffers[i];
+		for (i = 0; i < result->data->row_count; i++) {
+			current_row = set->data[i];
+			current_buffer = set->row_buffers[i];
 			for (j = 0; j < result->field_count; j++) {
 				if (result->type == MYSQLND_RES_PS) {
 					/* For now PS always does create copies when fetching data */
@@ -184,15 +189,18 @@
 																	   STAT_COPY_ON_WRITE_SAVED);
 				}
 			}
-			efree(current_row);
-			efree(current_buffer);
+			pefree(current_row, set->persistent);
+			pefree(current_buffer, set->persistent);
 		}
-		efree(result->data);
-		efree(result->row_buffers);
+		pefree(set->data, set->persistent);
+		pefree(set->row_buffers, set->persistent);
+		set->data			= NULL;
+		set->row_buffers	= NULL;
+		set->data_cursor	= NULL;
+		set->row_count	= 0;
+
+		pefree(set, set->persistent);
 		result->data		= NULL;
-		result->row_buffers	= NULL;
-		result->data_cursor = NULL;
-		result->row_count = 0;
 	}
 
 #ifndef WE_WANT_TO_USE_ROW_BUFFER_IN_ROWP_READ
@@ -1190,12 +1198,14 @@
 	  - first row hs not been read
 	  - last_row has been read
 	*/
-	if ((result->data_cursor == NULL) || result->data_cursor == result->data ||
-		((result->data_cursor - result->data) > result->row_count)) {
+	if (result->data->data_cursor == NULL ||
+		result->data->data_cursor == result->data->data ||
+		((result->data->data_cursor - result->data->data) >
result->data->row_count))
+	{
 		return NULL;/* No rows or no more rows */
 	}
 
-	previous_row = *(result->data_cursor - 1);
+	previous_row = *(result->data->data_cursor - 1);
 	for (i = 0; i < result->field_count; i++) {
 		result->lengths[i] = (Z_TYPE_P(previous_row[i]) == IS_NULL)?
0:Z_STRLEN_P(previous_row[i]);
 	}
@@ -1225,8 +1235,9 @@
 	php_mysql_packet_row	*row_packet = result->row_packet;
 	unsigned long			*lengths = result->lengths;
 
-	if (result->eof_reached) {
+	if (result->unbuf->eof_reached) {
 		/* No more rows obviously */
+		*fetched_anything = FALSE;
 		return PASS;
 	}
 	if (result->conn->state != CONN_FETCHING_DATA) {
@@ -1244,12 +1255,12 @@
 	if (PASS == (ret = PACKET_READ(row_packet, result->conn)) &&
!row_packet->eof) {
 		mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
 
-		result->last_row_data = row_packet->fields;
-		result->last_row_buffer = row_packet->row_buffer;
+		result->unbuf->last_row_data = row_packet->fields;
+		result->unbuf->last_row_buffer = row_packet->row_buffer;
 		row_packet->fields = NULL;
 		row_packet->row_buffer = NULL;
 
-		result->row_count++;
+		result->unbuf->row_count++;
 		*fetched_anything = TRUE;
 
 		MYSQLND_INC_CONN_STATISTIC(&result->conn->stats,
STAT_ROWS_FETCHED_FROM_CLIENT);
@@ -1257,7 +1268,7 @@
 		if (!row_packet->skip_extraction) {
 			HashTable *row_ht = Z_ARRVAL_P(row);
 			for (i = 0; i < field_count; i++) {
-				zval *data = result->last_row_data[i];
+				zval *data = result->unbuf->last_row_data[i];
 				int len = (Z_TYPE_P(data) == IS_NULL)? 0:Z_STRLEN_P(data);
 
 				if (lengths) {
@@ -1309,7 +1320,7 @@
 	} else if (row_packet->eof) {
 		/* Mark the connection as usable again */
 
-		result->eof_reached = TRUE;
+		result->unbuf->eof_reached = TRUE;
 		result->conn->upsert_status.warning_count = row_packet->warning_count;
 		result->conn->upsert_status.server_status = row_packet->server_status;
 		/*
@@ -1355,6 +1366,7 @@
 	result->type			= MYSQLND_RES_NORMAL;
 	result->m.fetch_row		= result->m.fetch_row_normal_unbuffered;
 	result->m.fetch_lengths	= mysqlnd_fetch_lengths_unbuffered;
+	result->unbuf			= ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
 
 	result->conn = conn->m->get_reference(conn);
 	/*
@@ -1384,8 +1396,10 @@
 	zval *row = (zval *) param;
 
 	/* If we haven't read everything */
-	if (result->data_cursor && (result->data_cursor - result->data) <
result->row_count) {
-		zval **current_row = *result->data_cursor;
+	if (result->data->data_cursor &&
+		(result->data->data_cursor - result->data->data) <
result->data->row_count)
+	{
+		zval **current_row = *result->data->data_cursor;
 		for (i = 0; i < result->field_count; i++) {
 			zval *data = current_row[i];
 
@@ -1430,10 +1444,10 @@
 				}
 			}
 		}
-		result->data_cursor++;
+		result->data->data_cursor++;
 		*fetched_anything = TRUE;
 	} else {
-		result->data_cursor = NULL;
+		result->data->data_cursor = NULL;
 		*fetched_anything = FALSE;
 #ifndef MYSQLND_SILENT
 		php_printf("NO MORE DATA\n ");
@@ -1454,6 +1468,7 @@
 	unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET, free_rows;
 	php_mysql_packet_row row_packet;
 	MYSQLND_RES *result;
+	zend_bool to_cache = FALSE;
 
 	if (!conn->current_result) {
 		return NULL;
@@ -1481,9 +1496,11 @@
 
 	/* Create room for 'next_extend' rows */
 
-	result->conn = NULL;	/* store result does not reference  the connection */
-	result->data 		= emalloc(next_extend * sizeof(zval **));
-	result->row_buffers = emalloc(next_extend * sizeof(zend_uchar *));
+	result->conn 		= NULL;	/* store result does not reference  the connection */
+	result->data 				= pecalloc(1, sizeof(MYSQLND_RES_BUFFERED), to_cache);
+	result->data->data 		  	= pemalloc(next_extend * sizeof(zval **), to_cache);
+	result->data->row_buffers 	= pemalloc(next_extend * sizeof(zend_uchar *),
to_cache);
+	result->data->persistent	= to_cache;
 
 	free_rows = next_extend;
 
@@ -1498,14 +1515,15 @@
 
 		if (!free_rows) {
 			unsigned long total_rows = free_rows = next_extend = next_extend * 5 / 3; /* extend
with 33% */
-			total_rows += result->row_count;
-			result->data = erealloc(result->data, total_rows * sizeof(zval **));
-			result->row_buffers = erealloc(result->row_buffers, total_rows *
sizeof(zend_uchar *));
+			total_rows += result->data->row_count;
+			result->data->data = perealloc(result->data->data, total_rows *
sizeof(zval **), to_cache);
+			result->data->row_buffers = perealloc(result->data->row_buffers,
+												  total_rows * sizeof(zend_uchar *), to_cache);
 		}
 		free_rows--;
-		current_row = result->data[result->row_count] = row_packet.fields;
-		result->row_buffers[result->row_count] = row_packet.row_buffer;
-		result->row_count++;
+		current_row = result->data->data[result->data->row_count] =
row_packet.fields;
+		result->data->row_buffers[result->data->row_count] = row_packet.row_buffer;
+		result->data->row_count++;
 
 		/* So row_packet's destructor function won't efree() it */
 		row_packet.fields = NULL;
@@ -1533,7 +1551,7 @@
 		*/
 	}
 	MYSQLND_INC_CONN_STATISTIC_W_VALUE(&conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT,
-									   result->row_count);
+									   result->data->row_count);
 
 	/* Finally clean */
 	if (row_packet.eof) { 
@@ -1551,10 +1569,10 @@
 
 	if (PASS == ret) {
 		/* Position at the first row */
-		result->data_cursor = result->data;
+		result->data->data_cursor = result->data->data;
 
 		/* libmysql's documentation says it should be so for SELECT statements */
-		conn->upsert_status.affected_rows = result->row_count;
+		conn->upsert_status.affected_rows = result->data->row_count;
 	} else {
 		mysqlnd_internal_free_result_contents(result TSRMLS_CC);
 		efree(result);
@@ -1577,7 +1595,9 @@
 	  A PS could be prepared - there is metadata and thus a stmt->result but the
 	  fetch_row function isn't actually set (NULL), thus we have to skip these.
 	*/
-	if (!result->data && result->conn && !result->eof_reached
&& result->m.fetch_row) {
+	if (!result->data && result->conn && result->unbuf &&
+		!result->unbuf->eof_reached && result->m.fetch_row)
+	{
 		/* We have to fetch all data to clean the line */
 		MYSQLND_INC_CONN_STATISTIC(&result->conn->stats,
 									result->type == MYSQLND_RES_NORMAL? STAT_FLUSHED_NORMAL_SETS:
@@ -1617,10 +1637,10 @@
 	}
 
 	/* libmysql just moves to the end, it does traversing of a linked list */
-	if (row >= result->row_count) {
-		result->data_cursor = NULL;
+	if (row >= result->data->row_count) {
+		result->data->data_cursor = NULL;
 	} else {
-		result->data_cursor = result->data + row;
+		result->data->data_cursor = result->data->data + row;
 	}
 
 	return PASS;
@@ -2021,7 +2041,7 @@
 mynd_ulonglong _mysqlnd_num_rows(const MYSQLND_RES * const res)
 {
 	/* Be compatible with libmysql. We count row_count, but will return 0 */
-	return res->data? res->row_count:0;
+	return res->data? res->data->row_count:0;
 }
 /* }}} */
 
@@ -2458,14 +2478,17 @@
 	ulong	i=0;
 
 	/* mysqlnd_fetch_all works with buffered resultsets only */
-	if (result->conn || !result->row_count || !result->data_cursor ||
-		result->data_cursor >= result->data + result->row_count) {
+	if (result->conn || !result->data ||
+		!result->data->row_count || !result->data->data_cursor ||
+		result->data->data_cursor >= result->data->data +
result->data->row_count) {
 		RETURN_NULL();
 	}	
 
-	mysqlnd_array_init(return_value, result->row_count);
+	mysqlnd_array_init(return_value, result->data->row_count);
 
-	while (result->data_cursor && (result->data_cursor - result->data) <
result->row_count) {
+	while (result->data->data_cursor &&
+		   (result->data->data_cursor - result->data->data) <
result->data->row_count)
+	{
 		MAKE_STD_ZVAL(row);
 		mysqlnd_fetch_into(result, flags, row);
 		add_index_zval(return_value, i++, row);

Modified: trunk/ext/mysqli/mysqlnd/mysqlnd.h
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd.h	2007-03-21 15:24:52 UTC (rev 242)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd.h	2007-03-21 19:07:06 UTC (rev 243)
@@ -697,6 +697,26 @@
 };
 
 
+typedef struct st_mysqlnd_buffered_result {
+	zval				***data;
+	zval				***data_cursor;
+	zend_uchar			**row_buffers;
+	zend_bool			persistent;
+	mynd_ulonglong		row_count;
+} MYSQLND_RES_BUFFERED;
+
+
+typedef struct st_mysqlnd_unbuffered_result {
+	/* For unbuffered (both normal and PS) */
+	zval				**last_row_data;
+	zend_uchar			*last_row_buffer;
+
+	mynd_ulonglong		row_count;
+
+	zend_bool			eof_reached;
+} MYSQLND_RES_UNBUFFERED;
+
+
 struct st_mysqlnd_res {
 	MYSQLND					*conn;
 	enum_mysqlnd_res_type	type;
@@ -708,35 +728,17 @@
 	unsigned int					current_field;
 
 	/* To be used with store_result() - both normal and PS */
-	zval				***data;
-	zval				***data_cursor;
-	zend_uchar			**row_buffers;
+	MYSQLND_RES_BUFFERED * data;
 
+	MYSQLND_RES_UNBUFFERED * unbuf;
 
-	/* For unbuffered (both normal and PS) */
-	zval				**last_row_data;
-	zend_uchar			*last_row_buffer;
-
-	/* For old-API myslqnd_fetch_row() */
-	MYSQLND_ROW			last_row;
-
 	/*
 	  Column lengths of current row - both buffered and unbuffered.
 	  For buffered results it duplicates the data found in **data 
 	*/
 	unsigned long		*lengths;
 
-	/* To be used with use_result() */
-	zend_bool			eof_reached;
-
 	/*
-	  This is set at once with store_result() or grows with
-	  use_result(). To check whether the result set is unbuffered
-	  use 'conn', which is non-NULL in this case.
-	*/
-	mynd_ulonglong		row_count;
-
-	/*
 	  For future use in php_mysqlnd_rowp_read() .
 	  For one time allocation of the row buffer
 	*/
@@ -863,7 +865,7 @@
 #define mysqlnd_get_proto_info(conn)	(conn)->protocol_version
 #define mysqlnd_thread_id(conn)			(conn)->thread_id
 
-#define mysqlnd_num_rows(result)		((result)->data? (result)->row_count:0)
+#define mysqlnd_num_rows(result)		((result)->data? (result)->data->row_count:0)
 #define mysqlnd_num_fields(result)		(result)->field_count
 
 #define mysqlnd_fetch_lengths(result)	((result)->m.fetch_lengths?
(result)->m.fetch_lengths((result)):NULL)

Modified: trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c
===================================================================
--- trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c	2007-03-21 15:24:52 UTC (rev 242)
+++ trunk/ext/mysqli/mysqlnd/mysqlnd_ps.c	2007-03-21 19:07:06 UTC (rev 243)
@@ -65,6 +65,7 @@
 	int next_extend = 32, free_rows;
 	php_mysql_packet_row row_packet;
 	MYSQLND_RES *result;
+	zend_bool to_cache = FALSE;
 
 	/* be compliant with libmysql - NULL will turn */
 	if (!stmt->field_count) {
@@ -100,8 +101,10 @@
 		result->conn->m->free_reference(result->conn TSRMLS_CC);
 		result->conn = NULL;	/* store result does not reference  the connection */
 	}
-	result->data		= emalloc(next_extend * sizeof(zval **));
-	result->row_buffers = emalloc(next_extend * sizeof(zend_uchar *));
+	result->data			= pecalloc(1, sizeof(MYSQLND_RES_BUFFERED), to_cache);
+	result->data->data		= pemalloc(next_extend * sizeof(zval **), to_cache);
+	result->data->row_buffers = pemalloc(next_extend * sizeof(zend_uchar *),
to_cache);
+	result->data->persistent= to_cache;
 
 	free_rows = next_extend;
 
@@ -116,14 +119,15 @@
 
 		if (!free_rows) {
 			unsigned long total_rows = free_rows = next_extend = next_extend * 5 / 3; /* extend
with 33% */
-			total_rows += result->row_count;
-			result->data = erealloc(result->data, total_rows * sizeof(zval **));
-			result->row_buffers = erealloc(result->row_buffers, total_rows *
sizeof(zend_uchar *));
+			total_rows += result->data->row_count;
+			result->data->data = perealloc(result->data->data, total_rows *
sizeof(zval **), to_cache);
+			result->data->row_buffers = perealloc(result->data->row_buffers,
+												  total_rows * sizeof(zend_uchar *), to_cache);
 		}
 		free_rows--;
-		current_row = result->data[result->row_count] = row_packet.fields;
-		result->row_buffers[result->row_count] = row_packet.row_buffer;
-		result->row_count++;
+		current_row = result->data->data[result->data->row_count] =
row_packet.fields;
+		result->data->row_buffers[result->data->row_count] = row_packet.row_buffer;
+		result->data->row_count++;
 
 		/* So row_packet's destructor function won't efree() it */
 		row_packet.fields = NULL;
@@ -162,13 +166,13 @@
 
 	if (PASS == ret) {
 		/* Position at the first row */
-		result->data_cursor = result->data;
+		result->data->data_cursor = result->data->data;
 		stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;
 
 		/* libmysql API docs say it should be so for SELECT statements */
 		stmt->upsert_status.affected_rows =
 			stmt->conn->upsert_status.affected_rows =
-				stmt->result->row_count;
+				stmt->result->data->row_count;
 	} else {
 		mysqlnd_internal_free_result_contents(stmt->result TSRMLS_CC);
 		efree(stmt->result);
@@ -499,10 +503,12 @@
 	MYSQLND_STMT *stmt = (MYSQLND_STMT *) param;
 
 	/* If we haven't read everything */
-	if (result->data_cursor && (result->data_cursor - result->data) <
result->row_count) {
+	if (result->data->data_cursor &&
+		(result->data->data_cursor - result->data->data) <
result->data->row_count)
+	{
 		/* The user could have skipped binding - don't crash*/
 		if (stmt->result_bind) {
-			zval **current_row = *result->data_cursor;
+			zval **current_row = *result->data->data_cursor;
 			for (i = 0; i < result->field_count; i++) {
 				/* copy the type */
 				if (stmt->result_bind[i].bound == TRUE) {
@@ -523,10 +529,10 @@
 				}
 			}
 		}
-		result->data_cursor++;
+		result->data->data_cursor++;
 		*fetched_anything = TRUE;
 	} else {
-		result->data_cursor = NULL;
+		result->data->data_cursor = NULL;
 		*fetched_anything = FALSE;
 #ifndef MYSQLND_SILENT
 		php_printf("NO MORE DATA\n ");
@@ -547,8 +553,9 @@
 	unsigned int i, field_count = result->field_count;
 	php_mysql_packet_row *row_packet = result->row_packet;
 
-	if (result->eof_reached) {
+	if (result->unbuf->eof_reached) {
 		/* No more rows obviously */
+		*fetched_anything = FALSE;
 		return PASS;
 	}
 	if (result->conn->state != CONN_FETCHING_DATA) {
@@ -564,20 +571,20 @@
 	  mysqlnd_unbuffered_free_last_data() before it. The function returns always true.
 	*/
 	if (PASS == (ret = PACKET_READ(row_packet, result->conn)) &&
!row_packet->eof) {
-		result->row_count++;
+		result->unbuf->row_count++;
 		*fetched_anything = TRUE;
 
 		if (!row_packet->skip_extraction) {
 			mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
 
-			result->last_row_data = row_packet->fields;
-			result->last_row_buffer = row_packet->row_buffer;
+			result->unbuf->last_row_data = row_packet->fields;
+			result->unbuf->last_row_buffer = row_packet->row_buffer;
 			row_packet->fields = NULL;
 			row_packet->row_buffer = NULL;
 
 			for (i = 0; i < field_count; i++) {
 				if (stmt->result_bind[i].bound == TRUE) {
-					zval *data = result->last_row_data[i];
+					zval *data = result->unbuf->last_row_data[i];
 					/*
 					  stmt->result_bind[i].zv has been already destructed
 					  in mysqlnd_unbuffered_free_last_data()
@@ -613,7 +620,7 @@
 
 	/* Mark the connection as usable again */
 	if (row_packet->eof) {
-		result->eof_reached = TRUE;
+		result->unbuf->eof_reached = TRUE;
 		result->conn->upsert_status.warning_count = row_packet->warning_count;
 		result->conn->upsert_status.server_status = row_packet->server_status;
 		/*
@@ -659,6 +666,8 @@
 	result->m.fetch_lengths	= NULL; /* makes no sense */
 	result->zval_cache		= NULL;
 
+	result->unbuf	= ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+
 	/*
 	  Will be freed in the mysqlnd_internal_free_result_contents() called
 	  by the resource destructor. mysqlnd_fetch_row_unbuffered() expects
@@ -718,15 +727,15 @@
 		unsigned int i, field_count = result->field_count;
 		mysqlnd_unbuffered_free_last_data(result TSRMLS_CC);
 
-		result->last_row_data = row_packet->fields;
-		result->last_row_buffer = row_packet->row_buffer;
+		result->unbuf->last_row_data = row_packet->fields;
+		result->unbuf->last_row_buffer = row_packet->row_buffer;
 		row_packet->fields = NULL;
 		row_packet->row_buffer = NULL;
 		if (!row_packet->skip_extraction) {
 			/* If no result bind, do nothing. We consumed the data */
 			for (i = 0; i < field_count; i++) {
 				if (stmt->result_bind[i].bound == TRUE) {
-					zval *data = result->last_row_data[i];
+					zval *data = result->unbuf->last_row_data[i];
 					/*
 					  stmt->result_bind[i].zv has been already destructed
 					  in mysqlnd_unbuffered_free_last_data()
@@ -747,7 +756,7 @@
 				}
 			}
 		}
-		result->row_count++;
+		result->unbuf->row_count++;
 		*fetched_anything = TRUE;
 		/* We asked for one row, the next one should be EOF, eat it */
 		ret = PACKET_READ(row_packet, result->conn);
@@ -766,7 +775,7 @@
 			stmt->conn->upsert_status.server_status =
 				row_packet->server_status;
 
-		result->eof_reached = row_packet->eof;
+		result->unbuf->eof_reached = row_packet->eof;
 	}
 	stmt->upsert_status.warning_count =
 		stmt->conn->upsert_status.warning_count =
@@ -1203,7 +1212,8 @@
 	result = mysqlnd_result_init(stmt->field_count, cache);
 	result->type = MYSQLND_RES_NORMAL;
 	result->m.fetch_row = result->m.fetch_row_normal_unbuffered;
-	result->eof_reached = TRUE;
+	result->unbuf = ecalloc(1, sizeof(MYSQLND_RES_UNBUFFERED));
+	result->unbuf->eof_reached = TRUE;
 	result->fields=	mysqlnd_result_metadata_clone_metadata(stmt->result);
 
 	return result;

Thread
PHP mysqlnd svn commit: r243 - in trunk/ext/mysqli: . mysqlndahristov21 Mar