Skip to content

Commit 7e6f9a8

Browse files
committed
MNDR:
- split handle_response() into handle_OK and handle_EOF
1 parent aa4966d commit 7e6f9a8

File tree

4 files changed

+117
-184
lines changed

4 files changed

+117
-184
lines changed

ext/mysqlnd/mysqlnd.c

-103
Original file line numberDiff line numberDiff line change
@@ -356,109 +356,6 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn)
356356
}
357357
/* }}} */
358358

359-
#if 0
360-
/* {{{ mysqlnd_conn_data::send_command_handle_response */
361-
static enum_func_status
362-
MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(
363-
MYSQLND_CONN_DATA * const conn,
364-
const enum mysqlnd_packet_type ok_packet,
365-
const zend_bool silent,
366-
const enum php_mysqlnd_server_command command,
367-
const zend_bool ignore_upsert_status)
368-
{
369-
enum_func_status ret = FAIL;
370-
371-
DBG_ENTER("mysqlnd_conn_data::send_command_handle_response");
372-
DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
373-
374-
switch (ok_packet) {
375-
case PROT_OK_PACKET:{
376-
MYSQLND_PACKET_OK * ok_response = conn->payload_decoder_factory->m.get_ok_packet(conn->payload_decoder_factory, FALSE);
377-
if (!ok_response) {
378-
SET_OOM_ERROR(conn->error_info);
379-
break;
380-
}
381-
if (FAIL == (ret = PACKET_READ(ok_response))) {
382-
if (!silent) {
383-
DBG_ERR_FMT("Error while reading %s's OK packet", mysqlnd_command_to_text[command]);
384-
php_error_docref(NULL, E_WARNING, "Error while reading %s's OK packet. PID=%u",
385-
mysqlnd_command_to_text[command], getpid());
386-
}
387-
} else {
388-
DBG_INF_FMT("OK from server");
389-
if (0xFF == ok_response->field_count) {
390-
/* The server signalled error. Set the error */
391-
SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
392-
ret = FAIL;
393-
/*
394-
Cover a protocol design error: error packet does not
395-
contain the server status. Therefore, the client has no way
396-
to find out whether there are more result sets of
397-
a multiple-result-set statement pending. Luckily, in 5.0 an
398-
error always aborts execution of a statement, wherever it is
399-
a multi-statement or a stored procedure, so it should be
400-
safe to unconditionally turn off the flag here.
401-
*/
402-
conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
403-
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
404-
} else {
405-
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
406-
ok_response->message, ok_response->message_len,
407-
conn->persistent);
408-
409-
if (!ignore_upsert_status) {
410-
UPSERT_STATUS_RESET(conn->upsert_status);
411-
conn->upsert_status->warning_count = ok_response->warning_count;
412-
conn->upsert_status->server_status = ok_response->server_status;
413-
conn->upsert_status->affected_rows = ok_response->affected_rows;
414-
conn->upsert_status->last_insert_id = ok_response->last_insert_id;
415-
}
416-
}
417-
}
418-
PACKET_FREE(ok_response);
419-
break;
420-
}
421-
case PROT_EOF_PACKET:{
422-
MYSQLND_PACKET_EOF * ok_response = conn->payload_decoder_factory->m.get_eof_packet(conn->payload_decoder_factory, FALSE);
423-
if (!ok_response) {
424-
SET_OOM_ERROR(conn->error_info);
425-
break;
426-
}
427-
if (FAIL == (ret = PACKET_READ(ok_response))) {
428-
SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
429-
"Malformed packet");
430-
if (!silent) {
431-
DBG_ERR_FMT("Error while reading %s's EOF packet", mysqlnd_command_to_text[command]);
432-
php_error_docref(NULL, E_WARNING, "Error while reading %s's EOF packet. PID=%d",
433-
mysqlnd_command_to_text[command], getpid());
434-
}
435-
} else if (0xFF == ok_response->field_count) {
436-
/* The server signalled error. Set the error */
437-
SET_CLIENT_ERROR(conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
438-
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
439-
} else if (0xFE != ok_response->field_count) {
440-
SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
441-
if (!silent) {
442-
DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count);
443-
php_error_docref(NULL, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X",
444-
ok_response->field_count);
445-
}
446-
} else {
447-
DBG_INF_FMT("OK from server");
448-
}
449-
PACKET_FREE(ok_response);
450-
break;
451-
}
452-
default:
453-
SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
454-
php_error_docref(NULL, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
455-
break;
456-
}
457-
DBG_INF(ret == PASS ? "PASS":"FAIL");
458-
DBG_RETURN(ret);
459-
}
460-
/* }}} */
461-
#endif
462359

463360
/* {{{ mysqlnd_conn_data::set_server_option */
464361
static enum_func_status

ext/mysqlnd/mysqlnd_loaddata.c

+6-2
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
136136
/* }}} */
137137

138138

139-
static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
139+
static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of a local file";
140140

141141

142142
/* {{{ mysqlnd_handle_local_infile */
@@ -213,7 +213,11 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filenam
213213
infile_error:
214214
/* get response from server and update upsert values */
215215
if (FAIL == send_command_handle_response(PROT_OK_PACKET, FALSE, COM_QUERY, FALSE,
216-
conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent)) {
216+
conn->error_info,
217+
conn->upsert_status,
218+
conn->payload_decoder_factory,
219+
&conn->last_message,
220+
conn->persistent)) {
217221
result = FAIL;
218222
}
219223

ext/mysqlnd/mysqlnd_priv.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,8 @@
7878

7979
void mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status);
8080

81-
#define UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(status) (status)->m->set_affected_rows_to_error((status))
82-
#define UPSERT_STATUS_RESET(status) (status)->m->reset((status))
81+
#define UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(status) (status)->m->set_affected_rows_to_error((status))
82+
#define UPSERT_STATUS_RESET(status) (status)->m->reset((status))
8383

8484
/* Error handling */
8585
#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \

ext/mysqlnd/mysqlnd_wireprotocol.c

+109-77
Original file line numberDiff line numberDiff line change
@@ -2730,13 +2730,113 @@ send_command(
27302730
/* }}} */
27312731

27322732

2733+
/* {{{ send_command_handle_OK */
2734+
static enum_func_status
2735+
send_command_handle_OK(MYSQLND_ERROR_INFO * const error_info,
2736+
MYSQLND_UPSERT_STATUS * const upsert_status,
2737+
MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory,
2738+
const zend_bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */
2739+
MYSQLND_STRING * const last_message,
2740+
const zend_bool last_message_persistent)
2741+
{
2742+
enum_func_status ret = FAIL;
2743+
MYSQLND_PACKET_OK * ok_response = payload_decoder_factory->m.get_ok_packet(payload_decoder_factory, FALSE);
2744+
2745+
DBG_ENTER("send_command_handle_OK");
2746+
if (!ok_response) {
2747+
SET_OOM_ERROR(error_info);
2748+
DBG_RETURN(FAIL);
2749+
}
2750+
if (FAIL == (ret = PACKET_READ(ok_response))) {
2751+
DBG_INF("Error while reading OK packet");
2752+
SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
2753+
goto end;
2754+
}
2755+
DBG_INF_FMT("OK from server");
2756+
if (0xFF == ok_response->field_count) {
2757+
/* The server signalled error. Set the error */
2758+
SET_CLIENT_ERROR(error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
2759+
ret = FAIL;
2760+
/*
2761+
Cover a protocol design error: error packet does not
2762+
contain the server status. Therefore, the client has no way
2763+
to find out whether there are more result sets of
2764+
a multiple-result-set statement pending. Luckily, in 5.0 an
2765+
error always aborts execution of a statement, wherever it is
2766+
a multi-statement or a stored procedure, so it should be
2767+
safe to unconditionally turn off the flag here.
2768+
*/
2769+
upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
2770+
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
2771+
} else {
2772+
SET_NEW_MESSAGE(last_message->s, last_message->l,
2773+
ok_response->message, ok_response->message_len,
2774+
last_message_persistent);
2775+
if (!ignore_upsert_status) {
2776+
UPSERT_STATUS_RESET(upsert_status);
2777+
upsert_status->warning_count = ok_response->warning_count;
2778+
upsert_status->server_status = ok_response->server_status;
2779+
upsert_status->affected_rows = ok_response->affected_rows;
2780+
upsert_status->last_insert_id = ok_response->last_insert_id;
2781+
} else {
2782+
/* LOAD DATA */
2783+
}
2784+
}
2785+
end:
2786+
PACKET_FREE(ok_response);
2787+
DBG_INF(ret == PASS ? "PASS":"FAIL");
2788+
DBG_RETURN(ret);
2789+
}
2790+
/* }}} */
2791+
2792+
2793+
/* {{{ send_command_handle_EOF */
2794+
enum_func_status
2795+
send_command_handle_EOF(MYSQLND_ERROR_INFO * const error_info,
2796+
MYSQLND_UPSERT_STATUS * const upsert_status,
2797+
MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory)
2798+
{
2799+
enum_func_status ret = FAIL;
2800+
MYSQLND_PACKET_EOF * response = payload_decoder_factory->m.get_eof_packet(payload_decoder_factory, FALSE);
2801+
2802+
DBG_ENTER("send_command_handle_EOF");
2803+
2804+
if (!response) {
2805+
SET_OOM_ERROR(error_info);
2806+
DBG_RETURN(FAIL);
2807+
}
2808+
if (FAIL == (ret = PACKET_READ(response))) {
2809+
DBG_INF("Error while reading EOF packet");
2810+
SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
2811+
} else if (0xFF == response->field_count) {
2812+
/* The server signalled error. Set the error */
2813+
DBG_INF_FMT("Error_no=%d SQLstate=%s Error=%s", response->error_no, response->sqlstate, response->error);
2814+
2815+
SET_CLIENT_ERROR(error_info, response->error_no, response->sqlstate, response->error);
2816+
2817+
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
2818+
} else if (0xFE != response->field_count) {
2819+
SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
2820+
DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", response->field_count);
2821+
php_error_docref(NULL, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X", response->field_count);
2822+
} else {
2823+
DBG_INF_FMT("EOF from server");
2824+
}
2825+
PACKET_FREE(response);
2826+
2827+
DBG_INF(ret == PASS ? "PASS":"FAIL");
2828+
DBG_RETURN(ret);
2829+
}
2830+
/* }}} */
2831+
2832+
27332833
/* {{{ send_command_handle_response */
27342834
enum_func_status
27352835
send_command_handle_response(
27362836
const enum mysqlnd_packet_type ok_packet,
27372837
const zend_bool silent,
27382838
const enum php_mysqlnd_server_command command,
2739-
const zend_bool ignore_upsert_status,
2839+
const zend_bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */
27402840

27412841
MYSQLND_ERROR_INFO * error_info,
27422842
MYSQLND_UPSERT_STATUS * upsert_status,
@@ -2751,88 +2851,20 @@ send_command_handle_response(
27512851
DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
27522852

27532853
switch (ok_packet) {
2754-
case PROT_OK_PACKET:{
2755-
MYSQLND_PACKET_OK * ok_response = payload_decoder_factory->m.get_ok_packet(payload_decoder_factory, FALSE);
2756-
if (!ok_response) {
2757-
SET_OOM_ERROR(error_info);
2758-
break;
2759-
}
2760-
if (FAIL == (ret = PACKET_READ(ok_response))) {
2761-
if (!silent) {
2762-
DBG_ERR_FMT("Error while reading %s's OK packet", mysqlnd_command_to_text[command]);
2763-
php_error_docref(NULL, E_WARNING, "Error while reading %s's OK packet. PID=%u",
2764-
mysqlnd_command_to_text[command], getpid());
2765-
}
2766-
} else {
2767-
DBG_INF_FMT("OK from server");
2768-
if (0xFF == ok_response->field_count) {
2769-
/* The server signalled error. Set the error */
2770-
SET_CLIENT_ERROR(error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
2771-
ret = FAIL;
2772-
/*
2773-
Cover a protocol design error: error packet does not
2774-
contain the server status. Therefore, the client has no way
2775-
to find out whether there are more result sets of
2776-
a multiple-result-set statement pending. Luckily, in 5.0 an
2777-
error always aborts execution of a statement, wherever it is
2778-
a multi-statement or a stored procedure, so it should be
2779-
safe to unconditionally turn off the flag here.
2780-
*/
2781-
upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
2782-
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
2783-
} else {
2784-
SET_NEW_MESSAGE(last_message->s, last_message->l,
2785-
ok_response->message, ok_response->message_len,
2786-
last_message_persistent);
2787-
2788-
if (!ignore_upsert_status) {
2789-
UPSERT_STATUS_RESET(upsert_status);
2790-
upsert_status->warning_count = ok_response->warning_count;
2791-
upsert_status->server_status = ok_response->server_status;
2792-
upsert_status->affected_rows = ok_response->affected_rows;
2793-
upsert_status->last_insert_id = ok_response->last_insert_id;
2794-
}
2795-
}
2796-
}
2797-
PACKET_FREE(ok_response);
2854+
case PROT_OK_PACKET:
2855+
ret = send_command_handle_OK(error_info, upsert_status, payload_decoder_factory, ignore_upsert_status, last_message, last_message_persistent);
27982856
break;
2799-
}
2800-
case PROT_EOF_PACKET:{
2801-
MYSQLND_PACKET_EOF * ok_response = payload_decoder_factory->m.get_eof_packet(payload_decoder_factory, FALSE);
2802-
if (!ok_response) {
2803-
SET_OOM_ERROR(error_info);
2804-
break;
2805-
}
2806-
if (FAIL == (ret = PACKET_READ(ok_response))) {
2807-
SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
2808-
"Malformed packet");
2809-
if (!silent) {
2810-
DBG_ERR_FMT("Error while reading %s's EOF packet", mysqlnd_command_to_text[command]);
2811-
php_error_docref(NULL, E_WARNING, "Error while reading %s's EOF packet. PID=%d",
2812-
mysqlnd_command_to_text[command], getpid());
2813-
}
2814-
} else if (0xFF == ok_response->field_count) {
2815-
/* The server signalled error. Set the error */
2816-
SET_CLIENT_ERROR(error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
2817-
UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
2818-
} else if (0xFE != ok_response->field_count) {
2819-
SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
2820-
if (!silent) {
2821-
DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count);
2822-
php_error_docref(NULL, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X",
2823-
ok_response->field_count);
2824-
}
2825-
} else {
2826-
DBG_INF_FMT("OK from server");
2827-
}
2828-
PACKET_FREE(ok_response);
2857+
case PROT_EOF_PACKET:
2858+
ret = send_command_handle_EOF(error_info, upsert_status, payload_decoder_factory);
28292859
break;
2830-
}
28312860
default:
28322861
SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
28332862
php_error_docref(NULL, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
28342863
break;
28352864
}
2865+
if (!silent && error_info->error_no == CR_MALFORMED_PACKET) {
2866+
php_error_docref(NULL, E_WARNING, "Error while reading %s's response packet. PID=%d", mysqlnd_command_to_text[command], getpid());
2867+
}
28362868
DBG_INF(ret == PASS ? "PASS":"FAIL");
28372869
DBG_RETURN(ret);
28382870
}
@@ -2942,7 +2974,7 @@ mysqlnd_com_debug_run(void *cmd)
29422974
conn->m->send_close,
29432975
conn);
29442976
if (PASS == ret) {
2945-
ret = send_command_handle_response(PROT_EOF_PACKET, COM_DEBUG, COM_DEBUG, TRUE,
2977+
ret = send_command_handle_response(PROT_EOF_PACKET, FALSE, COM_DEBUG, TRUE,
29462978
conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
29472979
}
29482980

0 commit comments

Comments
 (0)