List:Commits« Previous MessageNext Message »
From:ahristov Date:July 21 2007 1:54am
Subject:PHP mysqlnd svn commit: r824 - in trunk: mysqlnd tests/ext/mysqli
View as plain text  
Author: ahristov
Date: 2007-07-21 01:54:52 +0200 (Sat, 21 Jul 2007)
New Revision: 824

Modified:
   trunk/mysqlnd/mysqlnd.h
   trunk/mysqlnd/mysqlnd_palloc.c
   trunk/mysqlnd/mysqlnd_priv.h
   trunk/mysqlnd/mysqlnd_ps.c
   trunk/mysqlnd/mysqlnd_ps_codec.c
   trunk/mysqlnd/mysqlnd_result.c
   trunk/mysqlnd/mysqlnd_result_meta.c
   trunk/mysqlnd/mysqlnd_wireprotocol.c
   trunk/mysqlnd/mysqlnd_wireprotocol.h
   trunk/mysqlnd/portability.h
   trunk/tests/ext/mysqli/mysqli_fetch_assoc_bit.phpt
   trunk/tests/ext/mysqli/mysqli_stmt_fetch_bit.phpt
   trunk/tests/ext/mysqli/mysqli_stmt_get_result_bit.phpt
Log:
Eventually BIT handing is solved. Strangely BIT is sent
in different order, on the wire, than typical 1, 2, 3, 4, 8
byte types. This confuses a lot.

Down to 16 failures in Unicode, mysql+mysqli@mysqlnd, 5.1 Server


Modified: trunk/mysqlnd/mysqlnd.h
===================================================================
--- trunk/mysqlnd/mysqlnd.h	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd.h	2007-07-20 23:54:52 UTC (rev 824)
@@ -536,6 +536,9 @@
 	struct mysqlnd_field_hash_key	*zend_hash_keys;
 	unsigned int					current_field;
 	unsigned int					field_count;
+	/* We need this to make fast allocs in rowp_read */
+	unsigned int					bit_fields_count;
+	size_t							bit_fields_total_len; /* trailing \0 not counted */
 
 	struct st_mysqlnd_res_meta_methods *m;
 };

Modified: trunk/mysqlnd/mysqlnd_palloc.c
===================================================================
--- trunk/mysqlnd/mysqlnd_palloc.c	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_palloc.c	2007-07-20 23:54:52 UTC (rev 824)
@@ -355,7 +355,7 @@
 		  because the zvals from the cache are owned by it.
 		*/
 		if (type == MYSQLND_RES_PS_BUF || type == MYSQLND_RES_PS_UNBUF) {
-			ZVAL_REFCOUNT(*zv) = 1;			
+			; /* do nothing, zval_ptr_dtor will do the job*/
 		} else if (ZVAL_REFCOUNT(*zv) > 1) {
 			/*
 			  Not a prepared statement, then we have to
@@ -376,11 +376,6 @@
 			}
 			*copy_ctor_called = TRUE;
 		} else {
-			/*
-			  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);
 			}

Modified: trunk/mysqlnd/mysqlnd_priv.h
===================================================================
--- trunk/mysqlnd/mysqlnd_priv.h	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_priv.h	2007-07-20 23:54:52 UTC (rev 824)
@@ -174,7 +174,12 @@
 void mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uchar
**p,
 										size_t *buf_len, unsigned int null_byte_offset);
 
+void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
+								uint pack_len, zend_uchar **row, zend_bool as_unicode,
+								unsigned int byte_count, zend_bool is_bit TSRMLS_DC);
 
+
+
 int mysqlnd_set_sock_no_delay(php_stream *stream);
 #endif	/* MYSQLND_PRIV_H */
 

Modified: trunk/mysqlnd/mysqlnd_ps.c
===================================================================
--- trunk/mysqlnd/mysqlnd_ps.c	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_ps.c	2007-07-20 23:54:52 UTC (rev 824)
@@ -700,6 +700,8 @@
 	result->row_packet->field_count = result->field_count;
 	result->row_packet->binary_protocol = TRUE;
 	result->row_packet->fields_metadata = stmt->result->meta->fields;
+	result->row_packet->bit_fields_count = result->meta->bit_fields_count;
+	result->row_packet->bit_fields_total_len =
result->meta->bit_fields_total_len;
 	result->lengths = NULL;
 
 	stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;

Modified: trunk/mysqlnd/mysqlnd_ps_codec.c
===================================================================
--- trunk/mysqlnd/mysqlnd_ps_codec.c	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_ps_codec.c	2007-07-20 23:54:52 UTC (rev 824)
@@ -64,8 +64,79 @@
 #define MYSQLND_PS_SKIP_RESULT_W_LEN	-1
 #define MYSQLND_PS_SKIP_RESULT_STR		-2
 
+/* {{{ ps_fetch_from_1_to_8_bytes */
+void ps_fetch_from_1_to_8_bytes(zval *zv, const MYSQLND_FIELD * const field,
+								uint pack_len, zend_uchar **row, zend_bool as_unicode,
+								unsigned int byte_count, zend_bool is_bit TSRMLS_DC)
+{
+	char tmp[22];
+	size_t tmp_len = 0;
+	if (field->flags & UNSIGNED_FLAG) {
+		my_uint64 uval = 0;
 
+		switch (byte_count) {
+			case 8:uval = is_bit? (my_uint64) bit_uint8korr(*row):(my_uint64)
uint8korr(*row);break;
+			case 7:uval = bit_uint7korr(*row);break;
+			case 6:uval = bit_uint6korr(*row);break;
+			case 5:uval = bit_uint5korr(*row);break;
+			case 4:uval = is_bit? (my_uint64) bit_uint4korr(*row):(my_uint64)
uint4korr(*row);break;
+			case 3:uval = is_bit? (my_uint64) bit_uint3korr(*row):(my_uint64)
uint3korr(*row);break;
+			case 2:uval = is_bit? (my_uint64) bit_uint2korr(*row):(my_uint64)
uint2korr(*row);break;
+			case 1:uval = (my_uint64) uint1korr(*row);break;
+		}
 
+#if SIZEOF_LONG==4
+		if (uval > INT_MAX) {
+			tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
+		} else 
+#endif /* #if SIZEOF_LONG==4 */
+		{
+			if (byte_count < 8 || uval <= L64(9223372036854775807)) {
+				ZVAL_LONG(zv, uval);
+			} else {
+				tmp_len = sprintf((char *)&tmp, MYSQLND_LLU_SPEC, uval);
+			}
+		}
+	} else {
+		/* SIGNED */
+		my_int64 lval = 0;
+		switch (byte_count) {
+			case 8:lval = (my_int64) sint8korr(*row);break;
+			/*
+			  7, 6 and 5 are not possible.
+			  BIT is only unsigned, thus only uint5|6|7 macroses exist
+			*/
+			case 4:lval = (my_int64) sint4korr(*row);break;
+			case 3:lval = (my_int64) sint3korr(*row);break;
+			case 2:lval = (my_int64) sint2korr(*row);break;
+			case 1:lval = (my_int64) *(my_int8*)*row;break;
+		}
+
+#if SIZEOF_LONG==4
+	    if ((L64(2147483647) < (my_int64) lval) || (L64(-2147483648) > (my_int64)
lval)) {
+			tmp_len = sprintf((char *)&tmp, MYSQLND_LL_SPEC, lval);
+		} else 
+#endif /* SIZEOF */
+		{
+			ZVAL_LONG(zv, lval);
+		}
+	}
+
+	if (tmp_len) {
+#if PHP_MAJOR_VERSION >= 6
+		if (as_unicode) {
+			ZVAL_UTF8_STRINGL(zv, tmp, tmp_len, ZSTR_DUPLICATE);
+		} else
+#endif
+		{
+			ZVAL_STRINGL(zv, tmp, tmp_len, 1);
+		}			
+	}
+	(*row)+= byte_count;
+}
+/* }}} */
+
+
 /* {{{ ps_fetch_null */
 static
 void ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field,
@@ -83,13 +154,15 @@
 				   uint pack_len, zend_uchar **row,
 				   zend_bool as_unicode TSRMLS_DC)
 {
-
+	ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 1, FALSE TSRMLS_CC);
+#if 0
 	if (field->flags & UNSIGNED_FLAG) {
 		ZVAL_LONG(zv, *(my_uint8*)*row);
 	} else {
 		ZVAL_LONG(zv, *(my_int8*)*row);
 	}
 	(*row)++;
+#endif
 }
 /* }}} */
 
@@ -100,12 +173,15 @@
 					uint pack_len, zend_uchar **row,
 					zend_bool as_unicode TSRMLS_DC)
 {
+	ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 2, FALSE TSRMLS_CC);
+#if 0
 	if (field->flags & UNSIGNED_FLAG) {
 		ZVAL_LONG(zv, (my_uint16) sint2korr(*row));
 	} else {
 		ZVAL_LONG(zv, (my_int16) sint2korr(*row));	
 	}
 	(*row)+= 2;
+#endif
 }
 /* }}} */
 
@@ -116,6 +192,9 @@
 					uint pack_len, zend_uchar **row,
 					zend_bool as_unicode TSRMLS_DC)
 {
+	ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 4, FALSE TSRMLS_CC);
+#if 0
+
 	if (field->flags & UNSIGNED_FLAG) {
 		my_uint32 uval;
 
@@ -151,6 +230,7 @@
 		ZVAL_LONG(zv, (my_int32) sint4korr(*row));
 	}
 	(*row)+= 4;
+#endif /* 0 */
 }
 /* }}} */
 
@@ -161,6 +241,9 @@
 					uint pack_len, zend_uchar **row,
 					zend_bool as_unicode TSRMLS_DC)
 {
+	ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 8, FALSE TSRMLS_CC);
+#if 0
+
 	my_uint64 llval = (my_uint64) sint8korr(*row);
 	zend_bool uns = field->flags & UNSIGNED_FLAG? TRUE:FALSE;
 	
@@ -168,8 +251,8 @@
 	if (uns == TRUE && llval > 9223372036854775807L) {
 #elif SIZEOF_LONG==4
 	if ((uns == TRUE && llval > L64(2147483647)) || 
-	    (uns == FALSE && (( L64(2147483647) < (my_int64) llval) ||
-		(L64(-2147483648) > (my_int64) llval))))
+	    (uns == FALSE && ((L64( 2147483647) < (my_int64) llval) ||
+						  (L64(-2147483648) > (my_int64) llval))))
 	{
 #endif
 		char tmp[22];
@@ -192,6 +275,7 @@
 		ZVAL_LONG(zv, (long) llval);
 	}
   	(*row)+= 8;
+#endif /* 0 */
 }
 /* }}} */
 
@@ -413,38 +497,11 @@
 /* {{{ ps_fetch_bit */
 static
 void ps_fetch_bit(zval *zv, const MYSQLND_FIELD * const field,
-					 uint pack_len, zend_uchar **row,
-					 zend_bool as_unicode TSRMLS_DC)
+				  uint pack_len, zend_uchar **row,
+				  zend_bool as_unicode TSRMLS_DC)
 {
 	unsigned long length= php_mysqlnd_net_field_length(row);
-	ps_field_fetch_func func = NULL;
-	switch (length) {
-		case 8:
-			func = ps_fetch_int64;
-			break;
-		case 4:
-		case 3:
-			func = ps_fetch_int32;
-			break;
-		case 2:
-			func = ps_fetch_int16;
-			break;
-		case 1:
-			func = ps_fetch_int8;
-			break;
-		default:
-			php_error_docref(NULL TSRMLS_CC, E_WARNING, "Serious error. Length is %llu", length);
-			break;
-	}
-	if (func) {
-		func(zv, field, length, row, as_unicode TSRMLS_CC);
-	}
-#if 0
-	/* Handle BIT here */
-	ZVAL_STRINGL(zv, (char *)*row, length, 1);	
-#endif
-
-	(*row) += length;
+	ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, length, TRUE
TSRMLS_CC);
 }
 /* }}} */
 
@@ -547,10 +604,10 @@
 	mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].is_possibly_blob = TRUE;
 	mysqlnd_ps_fetch_functions[MYSQL_TYPE_LONG_BLOB].can_ret_as_str_in_uni 	= TRUE;
 
-	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func			= ps_fetch_bit;
-	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len		= MYSQLND_PS_SKIP_RESULT_STR;
-	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type		= IS_STRING;
-	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].is_possibly_blob = TRUE;
+	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].func		= ps_fetch_bit;
+	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].pack_len	= 8;
+	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].php_type	= IS_LONG;
+	mysqlnd_ps_fetch_functions[MYSQL_TYPE_BIT].can_ret_as_str_in_uni = TRUE;
 
 	mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].func		= ps_fetch_string;
 	mysqlnd_ps_fetch_functions[MYSQL_TYPE_VAR_STRING].pack_len	= MYSQLND_PS_SKIP_RESULT_STR;

Modified: trunk/mysqlnd/mysqlnd_result.c
===================================================================
--- trunk/mysqlnd/mysqlnd_result.c	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_result.c	2007-07-20 23:54:52 UTC (rev 824)
@@ -573,6 +573,8 @@
 	result->row_packet->field_count = result->field_count;
 	result->row_packet->binary_protocol = FALSE;
 	result->row_packet->fields_metadata = result->meta->fields;
+	result->row_packet->bit_fields_count = result->meta->bit_fields_count;
+	result->row_packet->bit_fields_total_len =
result->meta->bit_fields_total_len;
 	result->lengths = ecalloc(result->field_count, sizeof(unsigned long));
 
 	/* No multithreading issues as we don't share the connection :) */
@@ -684,6 +686,8 @@
 	row_packet.field_count = meta->field_count;
 	row_packet.binary_protocol = binary_protocol;
 	row_packet.fields_metadata = meta->fields;
+	row_packet.bit_fields_count		= meta->bit_fields_count;
+	row_packet.bit_fields_total_len = meta->bit_fields_total_len;
 	/* Let the row packet fill our buffer and skip additional malloc + memcpy */
 	while (FAIL != (ret = PACKET_READ_ALLOCA(row_packet, conn)) && !row_packet.eof)
{
 		int i;

Modified: trunk/mysqlnd/mysqlnd_result_meta.c
===================================================================
--- trunk/mysqlnd/mysqlnd_result_meta.c	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_result_meta.c	2007-07-20 23:54:52 UTC (rev 824)
@@ -167,8 +167,41 @@
 			PACKET_FREE_ALLOCA(field_packet);
 			return FAIL;
 		}
+		if (meta->fields[i].type == MYSQL_TYPE_BIT) {
+			size_t field_len;
+			++meta->bit_fields_count;
+			/* .length is in bits */
+			field_len = meta->fields[i].length / 8;
+			/*
+			  If there is rest, add one byte :
+			  8 bits = 1 byte but 9 bits = 2 bytes
+			*/
+			if (meta->fields[i].length % 8) {
+				++field_len;
+			}
+			switch (field_len) {
+				case 8:
+				case 7:
+				case 6:
+				case 5:
+					meta->bit_fields_total_len += 20;/* 21 digis, no sign*/
+					break;
+				case 4:
+					meta->bit_fields_total_len += 10;/* 2 000 000 000*/
+					break;
+				case 3:
+					meta->bit_fields_total_len += 8;/*  12 000 000*/
+					break;
+				case 2:
+					meta->bit_fields_total_len += 5;/* 32 500 */
+					break;
+				case 1:
+					meta->bit_fields_total_len += 3;/* 120 */
+					break;
+			}
+			
+		}
 
-
 #if PHP_MAJOR_VERSION >= 6
 		if (UG(unicode)) {
 			UChar *ustr;

Modified: trunk/mysqlnd/mysqlnd_wireprotocol.c
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.c	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.c	2007-07-20 23:54:52 UTC (rev 824)
@@ -1129,7 +1129,8 @@
 
 static enum_func_status
 php_mysqlnd_read_row_ex(MYSQLND *conn, zend_uchar **buf, int buf_size,
-						size_t *data_size, zend_bool persistent_alloc TSRMLS_DC)
+						size_t *data_size, zend_bool persistent_alloc,
+						unsigned int prealloc_more_bytes TSRMLS_DC)
 {
 	enum_func_status ret = PASS;
 	mysqlnd_packet_header header;
@@ -1145,7 +1146,7 @@
 	  zero-length byte, don't read the body, there is no such.
 	*/
 
-	*data_size = 0;
+	*data_size = prealloc_more_bytes;
 	while (1) {
 		if (FAIL == mysqlnd_read_header(conn , &header TSRMLS_CC)) {
 			ret = FAIL;
@@ -1158,9 +1159,9 @@
 			first_iteration = FALSE;
 			/*
 			  We need a trailing \0 for the last string, in case of text-mode,
-			  to be able to implement read-only variables.
+			  to be able to implement read-only variables. Thus, we add + 1.
 			*/
-			p = new_buf = pemalloc(header.size + 1, persistent_alloc);
+			p = new_buf = pemalloc(*data_size + 1, persistent_alloc);
 			net->stream->chunk_size = header.size;
 		} else if (!first_iteration) {
 			/* Empty packet after MYSQLND_MAX_PACKET_SIZE packet. That's ok, break */
@@ -1192,6 +1193,7 @@
 	if (ret == PASS && new_buf) {
 		*buf = new_buf;
 	}
+	*data_size -= prealloc_more_bytes;
 	return ret;
 }
 
@@ -1256,6 +1258,7 @@
 	int i;
 	zend_bool last_field_was_string;
 	zval **current_field, **end_field, **start_field;
+	zend_uchar *bit_area = packet->row_buffer + data_size + 1; /* we allocate from here
*/
 	zend_bool as_unicode = conn->options.numeric_and_datetime_as_unicode;
 #ifdef MYSQLND_STRING_TO_INT_CONVERSION
 	zend_bool as_int = conn->options.int_and_year_as_int;
@@ -1282,14 +1285,13 @@
 		if (current_field > start_field && last_field_was_string) {
 			/*
 			  Normal queries: 
-			  We have to put \0 now to the end of the previous field,
-			  if it was a string. IS_NULL doesn't matter. Because we
-			  have already read our length, then we can overwrite it
-			  in the row buffer.
+			  We have to put \0 now to the end of the previous field, if it was
+			  a string. IS_NULL doesn't matter. Because we have already read our
+			  length, then we can overwrite it in the row buffer.
 			  This statement terminates the previous field, not the current one.
 
 			  NULL_LENGTH is encoded in one byte, so we can stick a \0 there.
-			  Any string length is encoded in at least one byte, so we can stick
+			  Any string's length is encoded in at least one byte, so we can stick
 			  a \0 there.
 			*/
 
@@ -1326,7 +1328,7 @@
 					if ((uns == TRUE && v > L64(2147483647)) || 
 						(uns == FALSE && (( L64(2147483647) < (my_int64) v) ||
 						(L64(-2147483648) > (my_int64) v))))
-#endif
+#endif /* SIZEOF */
 					{
 						ZVAL_STRINGL(*current_field, (char *)p, len, 0);
 					} else {
@@ -1336,6 +1338,40 @@
 				*(p + len) = save;
 			} else
 #endif
+			if (packet->fields_metadata[i].type == MYSQL_TYPE_BIT) {
+				/*
+				  BIT fields are specially handled. As they come as bit mask, we have
+				  to convert it to human-readable representation. As the bits take
+				  less space in the protocol than the numbers they represent, we don't
+				  have enough space in the packet buffer to overwrite inside.
+				  Thus, a bit more space is pre-allocated at the end of the buffer,
+				  see php_mysqlnd_rowp_read(). And we add the strings at the end.
+				  Definitely not nice, _hackish_ :(, but works.
+				*/
+				zend_uchar *start = bit_area;
+				ps_fetch_from_1_to_8_bytes(*current_field, &(packet->fields_metadata[i]),
+							   			   0, &p, as_unicode, len, TRUE TSRMLS_CC);
+				/*
+				  We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
+				  later in this function there will be an advancement.
+				*/
+				p -= len;
+				if (Z_TYPE_PP(current_field) == IS_LONG) {
+					bit_area += 1 + sprintf((char *)start, MYSQLND_LLU_SPEC,
+											(my_int64) Z_LVAL_PP(current_field));
+					ZVAL_UTF8_STRINGL(*current_field, start, bit_area - start - 1, 0);
+				} else if (Z_TYPE_PP(current_field) == IS_STRING){
+					memcpy(bit_area, Z_STRVAL_PP(current_field), Z_STRLEN_PP(current_field));
+					bit_area += Z_STRLEN_PP(current_field);
+					*bit_area++ = '\0';
+					zval_dtor(*current_field);
+					ZVAL_UTF8_STRINGL(*current_field, start, bit_area - start - 1, 0);
+				}
+				/*
+				  IS_UNICODE should not be specially handled. In unicode mode
+				  the buffers are not pointed - everything is copied.
+				*/
+			} else 
 #if PHP_MAJOR_VERSION < 6
 			{
 				ZVAL_STRINGL(*current_field, (char *)p, len, 0);
@@ -1358,6 +1394,7 @@
 
 			  XXX: Keep in mind that up there there is an open `else` in
 				   #ifdef MYSQLND_STRING_TO_INT_CONVERSION
+				   which will make with this `if` an `else if`.
 			*/
 			if ((perm_bind.is_possibly_blob == TRUE &&
 				 packet->fields_metadata[i].charsetnr == MYSQLND_BINARY_CHARSET_NR) ||
@@ -1368,15 +1405,14 @@
 			} else {
 				ZVAL_UTF8_STRINGL(*current_field, (char *)p, len, 0);
 			}
-			/*
-			  The zval cache will check and see that the type is IS_STRING.
-			  In this case it will call copy_ctor(). This is valid when
-			  allocated == TRUE . In this case we can't upcast. Thus for non-PS
-			  point_type doesn't matter much, as the valuable information is
-			  in the type of result set. Still good to set it.
-			*/
 			if (allocated == FALSE) {
-				/* we can upcast */
+				/*
+				  The zval cache will check and see that the type is IS_STRING.
+				  In this case it will call copy_ctor(). This is valid when
+				  allocated == TRUE . In this case we can't upcast. Thus for non-PS
+				  point_type doesn't matter much, as the valuable information is
+				  in the type of result set. Still good to set it.
+				*/
 				if (Z_TYPE_P(*current_field) == IS_STRING) {
 					((mysqlnd_zval *) obj)->point_type = MYSQLND_POINTS_INT_BUFFER;
 				} else {
@@ -1410,9 +1446,16 @@
 	size_t data_size = 0;
 	size_t old_chunk_size = net->stream->chunk_size;
 	php_mysql_packet_row *packet= (php_mysql_packet_row *) _packet;
+	size_t post_alloc_for_bit_fields = 0;
 
+	if (!packet->binary_protocol && packet->bit_fields_count) {
+		/* For every field we need terminating \0 */
+		post_alloc_for_bit_fields =
+			packet->bit_fields_total_len + packet->bit_fields_count;
+	}
+
 	ret = php_mysqlnd_read_row_ex(conn, &packet->row_buffer, 0, &data_size,
-								  packet->persistent_alloc
+								  packet->persistent_alloc, post_alloc_for_bit_fields
 								  TSRMLS_CC);
 	if (FAIL == ret) {
 		goto end;

Modified: trunk/mysqlnd/mysqlnd_wireprotocol.h
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.h	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.h	2007-07-20 23:54:52 UTC (rev 824)
@@ -259,6 +259,9 @@
 	zend_bool		binary_protocol;
 	zend_bool		persistent_alloc;
 	MYSQLND_FIELD	*fields_metadata;
+	/* We need this to alloc bigger bufs in non-PS mode */
+	unsigned int	bit_fields_count;
+	size_t			bit_fields_total_len; /* trailing \0 not counted */
 
 	/* If error packet, we use these */
 	mysqlnd_error_info	error_info;

Modified: trunk/mysqlnd/portability.h
===================================================================
--- trunk/mysqlnd/portability.h	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/mysqlnd/portability.h	2007-07-20 23:54:52 UTC (rev 824)
@@ -137,8 +137,52 @@
 
 
 #define int1store(T,A)	do { *((zend_uchar*) (T)) = (A); } while(0)
-#define uint1korr(A)	(*(((zend_uchar*)(A))))
+#define uint1korr(A)	(*(((uint8*)(A))))
 
+/* Bit values are sent in reverted order of bytes, compared to normal !!! */
+#define bit_uint2korr(A) ((uint16) (((uint16) (((uchar*) (A))[1])) +\
+									((uint16) (((uchar*) (A))[0]) << 8)))
+#define bit_uint3korr(A) ((uint32) (((uint32) (((uchar*) (A))[2])) +\
+									(((uint32) (((uchar*) (A))[1])) << 8) +\
+									(((uint32) (((uchar*) (A))[0])) << 16)))
+
+#define bit_uint4korr(A) ((uint32) (((uint32) (((uchar*) (A))[3])) +\
+									(((uint32) (((uchar*) (A))[2])) << 8) +\
+									(((uint32) (((uchar*) (A))[1])) << 16) +\
+									(((uint32) (((uchar*) (A))[0])) << 24)))
+
+#define bit_uint5korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+                                  (((uint32) ((uchar) (A)[1])) << 8) +\
+                                  (((uint32) ((uchar) (A)[2])) << 16) +\
+                                  (((uint32) ((uchar) (A)[3])) << 24)) +\
+                               (((ulonglong) ((uchar) (A)[4])) << 32))
+
+#define bit_uint6korr(A)	((ulonglong)(((uint32) (((uchar*) (A))[5])) +\
+									(((uint32) (((uchar*) (A))[4])) << 8) +\
+									(((uint32) (((uchar*) (A))[3])) << 16) +\
+									(((uint32) (((uchar*) (A))[2])) << 24)) +\
+									(((ulonglong) (((uint32) (((uchar*) (A))[1])) +\
+									(((uint32) (((uchar*) (A))[0]) << 8)))) << 32))
+
+#define bit_uint7korr(A)	((ulonglong)(((uint32) (((uchar*) (A))[6])) +\
+									(((uint32) (((uchar*) (A))[5])) << 8) +\
+									(((uint32) (((uchar*) (A))[4])) << 16) +\
+									(((uint32) (((uchar*) (A))[3])) << 24)) +\
+									(((ulonglong) (((uint32) (((uchar*) (A))[2])) +\
+									(((uint32) (((uchar*) (A))[1])) << 8) +\
+									(((uint32) (((uchar*) (A))[0])) << 16))) << 32))
+
+
+#define bit_uint8korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[7])) +\
+									(((uint32) (((uchar*) (A))[6])) << 8) +\
+									(((uint32) (((uchar*) (A))[5])) << 16) +\
+									(((uint32) (((uchar*) (A))[4])) << 24)) +\
+									(((ulonglong) (((uint32) (((uchar*) (A))[3])) +\
+									(((uint32) (((uchar*) (A))[2])) << 8) +\
+									(((uint32) (((uchar*) (A))[1])) << 16) +\
+									(((uint32) (((uchar*) (A))[0])) << 24))) << 32))
+
+
 /*
 ** Define-funktions for reading and storing in machine independent format
 **  (low byte first)
@@ -156,23 +200,15 @@
                    (((uint32) (uchar) (A)[1]) << 8) | \
                     ((uint32) (uchar) (A)[0])))
 #define sint4korr(A)  (*((long *) (A)))
+
 #define uint2korr(A)  (*((uint16 *) (A)))
 #define uint3korr(A)  (uint32) (((uint32) ((uchar) (A)[0])) +\
                                (((uint32) ((uchar) (A)[1])) << 8) +\
                                (((uint32) ((uchar) (A)[2])) << 16))
 #define uint4korr(A)  (*((unsigned long *) (A)))
-#define uint5korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
-                                  (((uint32) ((uchar) (A)[1])) << 8) +\
-                                  (((uint32) ((uchar) (A)[2])) << 16) +\
-                                  (((uint32) ((uchar) (A)[3])) << 24)) +\
-                               (((ulonglong) ((uchar) (A)[4])) << 32))
-/* From Andrey Hristov, based on uint5korr() */
-#define uint6korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
-                                  (((uint32) ((uchar) (A)[1])) << 8) +\
-                                  (((uint32) ((uchar) (A)[2])) << 16) +\
-                                  (((uint32) ((uchar) (A)[3])) << 24)) +\
-                                  (((ulonglong) ((uchar) (A)[4])) << 32)) +\
-                                  (((ulonglong) ((uchar) (A)[5])) << 40))
+
+
+
 #define uint8korr(A)    (*((ulonglong *) (A)))
 #define sint8korr(A)    (*((longlong *) (A)))
 #define int2store(T,A)    *((uint16*) (T))= (uint16) (A)
@@ -231,6 +267,7 @@
                               (((int32) ((uchar) (A)[1]) << 8)) +\
                               (((int32) ((uchar) (A)[2]) << 16)) +\
                               (((int32) ((int16) (A)[3]) << 24)))
+
 #define sint8korr(A)  (longlong) uint8korr(A)
 #define uint2korr(A)  (uint16) (((uint16) ((uchar) (A)[0])) +\
                                ((uint16) ((uchar) (A)[1]) << 8))
@@ -241,26 +278,47 @@
                                (((uint32) ((uchar) (A)[1])) << 8) +\
                                (((uint32) ((uchar) (A)[2])) << 16) +\
                                (((uint32) ((uchar) (A)[3])) << 24))
-#define uint5korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+#define bit_uint5korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
                                   (((uint32) ((uchar) (A)[1])) << 8) +\
                                   (((uint32) ((uchar) (A)[2])) << 16) +\
                                   (((uint32) ((uchar) (A)[3])) << 24)) +\
                                (((ulonglong) ((uchar) (A)[4])) << 32))
 /* From Andrey Hristov, based on uint5korr */
-#define uint6korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
-                                  (((uint32) ((uchar) (A)[1])) << 8) +\
-                                  (((uint32) ((uchar) (A)[2])) << 16) +\
-                                  (((uint32) ((uchar) (A)[3])) << 24)) +\
-                                  (((ulonglong) ((uchar) (A)[4])) << 32)) +\
-                                  (((ulonglong) ((uchar) (A)[5])) << 40))
-#define uint8korr(A)  ((ulonglong)(((uint32) ((uchar) (A)[0])) +\
-                                  (((uint32) ((uchar) (A)[1])) << 8) +\
-                                  (((uint32) ((uchar) (A)[2])) << 16) +\
-                                  (((uint32) ((uchar) (A)[3])) << 24)) +\
-                                  (((ulonglong) (((uint32) ((uchar) (A)[4])) +\
-                                  (((uint32) ((uchar) (A)[5])) << 8) +\
-                                  (((uint32) ((uchar) (A)[6])) << 16) +\
-                                  (((uint32) ((uchar) (A)[7])) << 24))) <<
32))
+#define bit_uint6korr(A)	((ulonglong)(((uint32) (((uchar*) (A))[5])) +\
+									(((uint32) (((uchar*) (A))[4])) << 8) +\
+									(((uint32) (((uchar*) (A))[3])) << 16) +\
+									(((uint32) (((uchar*) (A))[2])) << 24)) +\
+									(((ulonglong) (((uint32) (((uchar*) (A))[1])) +\
+									(((uint32) (((uchar*) (A))[0]) << 8)))) << 32))
+
+#define bit_uint7korr(A)	((ulonglong)(((uint32) (((uchar*) (A))[6])) +\
+									(((uint32) (((uchar*) (A))[5])) << 8) +\
+									(((uint32) (((uchar*) (A))[4])) << 16) +\
+									(((uint32) (((uchar*) (A))[3])) << 24)) +\
+									(((ulonglong) (((uint32) (((uchar*) (A))[2])) +\
+									(((uint32) (((uchar*) (A))[1])) << 8) +\
+									(((uint32) (((uchar*) (A))[0])) << 16))) << 32))
+
+
+#define bit_uint8korr(A) ((ulonglong)(((uint32) (((uchar*) (A))[7])) +\
+									(((uint32) (((uchar*) (A))[6])) << 8) +\
+									(((uint32) (((uchar*) (A))[5])) << 16) +\
+									(((uint32) (((uchar*) (A))[4])) << 24)) +\
+									(((ulonglong) (((uint32) (((uchar*) (A))[3])) +\
+									(((uint32) (((uchar*) (A))[2])) << 8) +\
+									(((uint32) (((uchar*) (A))[1])) << 16) +\
+									(((uint32) (((uchar*) (A))[0])) << 24))) << 32))
+
+#define uint8korr(A)	((ulonglong)(((uint32) ((uchar) (A)[0])) +\
+									(((uint32) ((uchar) (A)[1])) << 8) +\
+									(((uint32) ((uchar) (A)[2])) << 16) +\
+									(((uint32) ((uchar) (A)[3])) << 24)) +\
+									(((ulonglong) (((uint32) ((uchar) (A)[4])) +\
+									(((uint32) ((uchar) (A)[5])) << 8) +\
+									(((uint32) ((uchar) (A)[6])) << 16) +\
+									(((uint32) ((uchar) (A)[7])) << 24))) << 32))
+
+
 #define int2store(T,A)  do { uint def_temp= (uint) (A) ;\
                   *((uchar*) (T))  =  (uchar)(def_temp); \
                   *((uchar*) (T+1)) = (uchar)((def_temp >> 8)); } while (0)

Modified: trunk/tests/ext/mysqli/mysqli_fetch_assoc_bit.phpt
===================================================================
--- trunk/tests/ext/mysqli/mysqli_fetch_assoc_bit.phpt	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/tests/ext/mysqli/mysqli_fetch_assoc_bit.phpt	2007-07-20 23:54:52 UTC (rev 824)
@@ -46,16 +46,11 @@
 				printf("[006 - %d] Looks like the INSERT and/or SELECT has failed, expecting %s ?=
%s\n",
 								$bits, $row['id'], $row['_label0']);
 			}
-
-			debug_zval_dump($row);
-			die("no int?\n");
-
 		}
-
 	}
 
 	mysqli_close($link);
 	print "done!";
 ?>
 --EXPECTF--
-done!
\ No newline at end of file
+done!

Modified: trunk/tests/ext/mysqli/mysqli_stmt_fetch_bit.phpt
===================================================================
--- trunk/tests/ext/mysqli/mysqli_stmt_fetch_bit.phpt	2007-07-20 18:22:04 UTC (rev 823)
+++ trunk/tests/ext/mysqli/mysqli_stmt_fetch_bit.phpt	2007-07-20 23:54:52 UTC (rev 824)
@@ -35,6 +35,7 @@
 			$tests++;
 			$value = mt_rand(0, $max_value);
 			$sql = sprintf("INSERT INTO test(id, label) VALUES (%d, b'%s')", $value,
decbin($value));
+
 			if (!mysqli_stmt_prepare($stmt, $sql) ||
 					!mysqli_stmt_execute($stmt))
 				printf("[004 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt),
mysqli_stmt_error($stmt));
@@ -49,7 +50,7 @@
 			if (!mysqli_stmt_fetch($stmt))
 				printf("[006 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt),
mysqli_stmt_error($stmt));
 
-			if (($id != $_label0) || ($value != $_label0)) {
+			if (($id !== $_label0) || ($value !== $_label0)) {
 				printf("[007 - %d] Insert of %d in BIT(%d) column might have failed. MySQL reports
odd values, id = %s, _label0 = %s, label = %s.\n", $bits, $value, $bits, $id, $_label0,
$label);
 			}
 			if ($value != $label) {
@@ -66,4 +67,4 @@
 	print "done!";
 ?>
 --EXPECTF--
-done!
\ No newline at end of file
+done!

Modified: trunk/tests/ext/mysqli/mysqli_stmt_get_result_bit.phpt
===================================================================
--- trunk/tests/ext/mysqli/mysqli_stmt_get_result_bit.phpt	2007-07-20 18:22:04 UTC (rev
823)
+++ trunk/tests/ext/mysqli/mysqli_stmt_get_result_bit.phpt	2007-07-20 23:54:52 UTC (rev
824)
@@ -76,4 +76,4 @@
 	print "done!";
 ?>
 --EXPECTF--
-done!
\ No newline at end of file
+done!

Thread
PHP mysqlnd svn commit: r824 - in trunk: mysqlnd tests/ext/mysqliahristov21 Jul