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/mysqli | ahristov | 21 Jul |