Author: ahristov
Date: 2007-04-17 13:05:06 +0200 (Tue, 17 Apr 2007)
New Revision: 326
Modified:
trunk/mysqlnd/mysqlnd.c
trunk/mysqlnd/mysqlnd_ps.c
trunk/mysqlnd/mysqlnd_wireprotocol.c
trunk/mysqlnd/mysqlnd_wireprotocol.h
Log:
Fix hanging of mysqlnd when error comes as part of result set.
Platform for checking is
Bug #27876 SF with cyrillic variable name fails during execution
Which returns an error during execution. Thus no second EOF packet comes,
and the error packet wasn't recognised.
Modified: trunk/mysqlnd/mysqlnd.c
===================================================================
--- trunk/mysqlnd/mysqlnd.c 2007-04-17 10:05:50 UTC (rev 325)
+++ trunk/mysqlnd/mysqlnd.c 2007-04-17 11:05:06 UTC (rev 326)
@@ -1361,6 +1361,13 @@
}
}
}
+ } else if (ret == FAIL) {
+ if (row_packet->error_info.error_no) {
+ result->conn->error_info = row_packet->error_info;
+ }
+ *fetched_anything = FALSE;
+ result->conn->state = CONN_READY;
+ result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
/* Mark the connection as usable again */
@@ -1610,7 +1617,6 @@
conn->upsert_status.warning_count = row_packet.warning_count;
conn->upsert_status.server_status = row_packet.server_status;
}
- PACKET_FREE_ALLOCA(row_packet);
/* save some memory */
if (free_rows) {
result->data->data = perealloc(result->data->data,
@@ -1634,11 +1640,13 @@
/* libmysql's documentation says it should be so for SELECT statements */
conn->upsert_status.affected_rows = result->data->row_count;
} else {
- mysqlnd_internal_free_result_contents(result TSRMLS_CC);
- efree(result);
+ mysqlnd_internal_free_result(result TSRMLS_CC);
result = NULL;
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pretty serious error");
+ conn->error_info = row_packet.error_info;
}
+
+ PACKET_FREE_ALLOCA(row_packet);
+
return result;
}
/* }}} */
Modified: trunk/mysqlnd/mysqlnd_ps.c
===================================================================
--- trunk/mysqlnd/mysqlnd_ps.c 2007-04-17 10:05:50 UTC (rev 325)
+++ trunk/mysqlnd/mysqlnd_ps.c 2007-04-17 11:05:06 UTC (rev 326)
@@ -150,12 +150,11 @@
transfered above.
*/
}
- /* Finally clean */
if (row_packet.eof) {
+ /* Finally clean */
conn->upsert_status.warning_count = row_packet.warning_count;
conn->upsert_status.server_status = row_packet.server_status;
}
- PACKET_FREE_ALLOCA(row_packet);
/* We can realloc here to save some memory, if free_rows > 0 ?*/
if (conn->upsert_status.server_status & SERVER_MORE_RESULTS_EXISTS) {
@@ -177,11 +176,14 @@
mysqlnd_internal_free_result_contents(stmt->result TSRMLS_CC);
efree(stmt->result);
stmt->result = NULL;
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "Pretty serious error");
stmt->state = MYSQLND_STMT_PREPARED;
+ if (row_packet.error_info.error_no) {
+ conn->error_info = row_packet.error_info;
+ }
}
- conn->state = CONN_READY;
+ PACKET_FREE_ALLOCA(row_packet);
+
return result;
}
/* }}} */
Modified: trunk/mysqlnd/mysqlnd_wireprotocol.c
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.c 2007-04-17 10:05:50 UTC (rev 325)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.c 2007-04-17 11:05:06 UTC (rev 326)
@@ -717,8 +717,8 @@
}
}
/* }}} */
+
-
/* {{{ php_mysqlnd_eof_read */
static enum_func_status
php_mysqlnd_eof_read(void *_packet, MYSQLND *conn TSRMLS_DC)
@@ -1252,7 +1252,7 @@
if (uns == TRUE && v > 9223372036854775807L)
#elif SIZEOF_LONG==4
if ((uns == TRUE && v > L64(2147483647)) ||
- (uns == FALSE && (( L64(2147483647) < (my_int64) v) ||
+ (uns == FALSE && (( L64(2147483647) < (my_int64) v) ||
(L64(-2147483648) > (my_int64) v))))
#endif
{
@@ -1279,7 +1279,7 @@
to check if we need to call copy_ctor().
XXX: Keep in mind that up there there is an open `else` in
- #ifdef MYSQLND_STRING_TO_INT_CONVERSION
+ #ifdef MYSQLND_STRING_TO_INT_CONVERSION
*/
if ((perm_bind.is_possibly_blob == TRUE &&
packet->fields_metadata[i].charsetnr == MYSQLND_BINARY_CHARSET_NR) ||
@@ -1326,7 +1326,19 @@
/* packet->row_buffer is of size 'data_size + 1' */
packet->header.size = data_size;
- if ((*(p = packet->row_buffer)) == 0xFE && data_size < 8) { /* EOF */
+ if ((*(p = packet->row_buffer)) == 0xFF) {
+ /*
+ Error message as part of the result set,
+ not good but we should not hang. See:
+ Bug #27876 : SF with cyrillic variable name fails during execution
+ */
+ ret = FAIL;
+ php_mysqlnd_read_error_from_line(p + 1, data_size - 1,
+ packet->error_info.error,
+ sizeof(packet->error_info.error),
+ &packet->error_info.error_no,
+ packet->error_info.sqlstate);
+ } else if (*packet->row_buffer == 0xFE && data_size < 8) { /* EOF */
packet->eof = TRUE;
p++;
if (data_size > 1) {
@@ -1335,7 +1347,6 @@
packet->server_status = uint2korr(p);
/* Seems we have 3 bytes reserved for future use */
}
- goto end;
} else {
MYSQLND_INC_CONN_STATISTIC(&conn->stats, STAT_ROWS_FETCHED_FROM_SERVER);
@@ -1386,9 +1397,9 @@
/*
Don't free packet->fields :
- normal queries -> store_result() | fetch_row_unbuffered() will transfer
- the ownership and NULL it.
+ the ownership and NULL it.
- PS will pass in it the bound variables, we have to use them! and of course
- not free the array. As it is passed to us, we should not clean it ourselves.
+ not free the array. As it is passed to us, we should not clean it ourselves.
*/
if (!alloca) {
efree(p);
@@ -1455,7 +1466,8 @@
if (0xFF == packet->error_code) {
php_mysqlnd_read_error_from_line(p, data_size - 1,
- packet->error_info.error, sizeof(packet->error_info.error),
+ packet->error_info.error,
+ sizeof(packet->error_info.error),
&packet->error_info.error_no,
packet->error_info.sqlstate);
return PASS;
Modified: trunk/mysqlnd/mysqlnd_wireprotocol.h
===================================================================
--- trunk/mysqlnd/mysqlnd_wireprotocol.h 2007-04-17 10:05:50 UTC (rev 325)
+++ trunk/mysqlnd/mysqlnd_wireprotocol.h 2007-04-17 11:05:06 UTC (rev 326)
@@ -258,6 +258,9 @@
zend_bool skip_extraction;
zend_bool binary_protocol;
MYSQLND_FIELD *fields_metadata;
+
+ /* If error packet, we use these */
+ mysqlnd_error_info error_info;
};
| Thread |
|---|
| • PHP mysqlnd svn commit: r326 - trunk/mysqlnd | ahristov | 17 Apr |