diff options
-rw-r--r-- | ext/mysqlnd/mysqlnd.c | 390 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_priv.h | 5 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 104 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_structs.h | 6 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 14 |
5 files changed, 478 insertions, 41 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c index 3026b67c1f..a4a5294f40 100644 --- a/ext/mysqlnd/mysqlnd.c +++ b/ext/mysqlnd/mysqlnd.c @@ -32,10 +32,6 @@ extern MYSQLND_CHARSET *mysqlnd_charsets; - -struct st_mysqlnd_protocol_command * -mysqlnd_get_command(enum php_mysqlnd_server_command command, ...); - PHPAPI const char * const mysqlnd_old_passwd = "mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. " "Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will " "store a new, and more secure, hash value in mysql.user. If this user is used in other scripts executed by PHP 5.2 or earlier you might need to remove the old-passwords " @@ -351,26 +347,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_command_do_request)(MYSQLND_CONN_DATA * c /* }}} */ -/* {{{ mysqlnd_conn_data::simple_command */ -static enum_func_status -MYSQLND_METHOD(mysqlnd_conn_data, send_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, - const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, - zend_bool ignore_upsert_status) -{ - enum_func_status ret; - DBG_ENTER("mysqlnd_conn_data::send_command"); - - ret = conn->m->send_command_do_request(conn, command, arg, arg_len, silent, ignore_upsert_status); - if (PASS == ret && ok_packet != PROT_LAST) { - ret = conn->m->send_command_handle_response(conn, ok_packet, silent, command, ignore_upsert_status); - } - - DBG_INF(ret == PASS ? "PASS":"FAIL"); - DBG_RETURN(ret); -} -/* }}} */ - - /* {{{ mysqlnd_conn_data::set_server_option */ static enum_func_status MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option) @@ -3053,7 +3029,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data) MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state), MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state), - MYSQLND_METHOD(mysqlnd_conn_data, send_command), + MYSQLND_METHOD(mysqlnd_conn_data, send_command_do_request), MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response), MYSQLND_METHOD(mysqlnd_conn_data, restart_psession), MYSQLND_METHOD(mysqlnd_conn_data, end_psession), @@ -3075,7 +3051,6 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data) MYSQLND_METHOD(mysqlnd_conn_data, execute_init_commands), MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags), MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake), - MYSQLND_METHOD(mysqlnd_conn_data, send_command_do_request), MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name), MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d), @@ -3746,6 +3721,56 @@ mysqlnd_com_query_create_command(va_list args) } /* }}} */ +/************************** COM_CHANGE_USER ******************************************/ +struct st_mysqlnd_protocol_com_change_user_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_change_user_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING payload; + zend_bool silent; + } context; +}; + + +/* {{{ mysqlnd_com_change_user_run */ +static enum_func_status +mysqlnd_com_change_user_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_change_user_command * command = (struct st_mysqlnd_protocol_com_change_user_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_change_user_run"); + + ret = conn->m->send_command_do_request(conn, COM_CHANGE_USER, (zend_uchar*) command->context.payload.s, command->context.payload.l, command->context.silent, TRUE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_change_user_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_change_user_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_change_user_command * command; + DBG_ENTER("mysqlnd_com_change_user_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_change_user_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.payload = va_arg(args, MYSQLND_CSTRING); + command->context.silent = va_arg(args, unsigned int); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_change_user_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ + /************************** COM_REAP_RESULT ******************************************/ struct st_mysqlnd_protocol_com_reap_result_command @@ -3799,6 +3824,298 @@ mysqlnd_com_reap_result_create_command(va_list args) /* }}} */ +/************************** COM_STMT_PREPARE ******************************************/ +struct st_mysqlnd_protocol_com_stmt_prepare_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_stmt_prepare_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING query; + } context; +}; + + +/* {{{ mysqlnd_com_stmt_prepare_run */ +static enum_func_status +mysqlnd_com_stmt_prepare_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_stmt_prepare_command * command = (struct st_mysqlnd_protocol_com_stmt_prepare_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_stmt_prepare_run"); + + ret = conn->m->send_command_do_request(conn, COM_STMT_PREPARE, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE, TRUE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_stmt_prepare_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_stmt_prepare_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_stmt_prepare_command * command; + DBG_ENTER("mysqlnd_com_stmt_prepare_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_prepare_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.query = va_arg(args, MYSQLND_CSTRING); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_stmt_prepare_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ + + +/************************** COM_STMT_EXECUTE ******************************************/ +struct st_mysqlnd_protocol_com_stmt_execute_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_stmt_execute_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING payload; + } context; +}; + + +/* {{{ mysqlnd_com_stmt_execute_run */ +static enum_func_status +mysqlnd_com_stmt_execute_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_stmt_execute_command * command = (struct st_mysqlnd_protocol_com_stmt_execute_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_stmt_execute_run"); + + ret = conn->m->send_command_do_request(conn, COM_STMT_EXECUTE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, FALSE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_stmt_execute_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_stmt_execute_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_stmt_execute_command * command; + DBG_ENTER("mysqlnd_com_stmt_execute_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_execute_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.payload = va_arg(args, MYSQLND_CSTRING); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_stmt_execute_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ + + +/************************** COM_STMT_FETCH ******************************************/ +struct st_mysqlnd_protocol_com_stmt_fetch_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_stmt_fetch_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING payload; + } context; +}; + + +/* {{{ mysqlnd_com_stmt_fetch_run */ +static enum_func_status +mysqlnd_com_stmt_fetch_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_stmt_fetch_command * command = (struct st_mysqlnd_protocol_com_stmt_fetch_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_stmt_fetch_run"); + + ret = conn->m->send_command_do_request(conn, COM_STMT_FETCH, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, TRUE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_stmt_fetch_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_stmt_fetch_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_stmt_fetch_command * command; + DBG_ENTER("mysqlnd_com_stmt_fetch_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_fetch_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.payload = va_arg(args, MYSQLND_CSTRING); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_stmt_fetch_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ + + +/************************** COM_STMT_RESET ******************************************/ +struct st_mysqlnd_protocol_com_stmt_reset_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_stmt_reset_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING payload; + } context; +}; + + +/* {{{ mysqlnd_com_stmt_reset_run */ +static enum_func_status +mysqlnd_com_stmt_reset_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_stmt_reset_command * command = (struct st_mysqlnd_protocol_com_stmt_reset_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_stmt_reset_run"); + + ret = conn->m->send_command_do_request(conn, COM_STMT_RESET, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, TRUE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_stmt_reset_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_stmt_reset_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_stmt_reset_command * command; + DBG_ENTER("mysqlnd_com_stmt_reset_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_reset_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.payload = va_arg(args, MYSQLND_CSTRING); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_stmt_reset_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ + + +/************************** COM_STMT_SEND_LONG_DATA ******************************************/ +struct st_mysqlnd_protocol_com_stmt_send_long_data_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_stmt_send_long_data_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING payload; + } context; +}; + + +/* {{{ mysqlnd_com_stmt_send_long_data_run */ +static enum_func_status +mysqlnd_com_stmt_send_long_data_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_stmt_send_long_data_command * command = (struct st_mysqlnd_protocol_com_stmt_send_long_data_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_stmt_send_long_data_run"); + + ret = conn->m->send_command_do_request(conn, COM_STMT_SEND_LONG_DATA, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, TRUE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_stmt_send_long_data_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_stmt_send_long_data_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_stmt_send_long_data_command * command; + DBG_ENTER("mysqlnd_com_stmt_send_long_data_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_send_long_data_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.payload = va_arg(args, MYSQLND_CSTRING); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_stmt_send_long_data_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ + + +/************************** COM_STMT_CLOSE ******************************************/ +struct st_mysqlnd_protocol_com_stmt_close_command +{ + struct st_mysqlnd_protocol_command parent; + struct st_mysqlnd_com_stmt_close_context + { + MYSQLND_CONN_DATA * conn; + MYSQLND_CSTRING payload; + } context; +}; + + +/* {{{ mysqlnd_com_stmt_close_run */ +static enum_func_status +mysqlnd_com_stmt_close_run(void *cmd) +{ + struct st_mysqlnd_protocol_com_stmt_close_command * command = (struct st_mysqlnd_protocol_com_stmt_close_command *) cmd; + enum_func_status ret = FAIL; + MYSQLND_CONN_DATA * conn = command->context.conn; + + DBG_ENTER("mysqlnd_com_stmt_close_run"); + + ret = conn->m->send_command_do_request(conn, COM_STMT_CLOSE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, TRUE); + + DBG_RETURN(ret); +} +/* }}} */ + + +/* {{{ mysqlnd_com_stmt_close_create_command */ +static struct st_mysqlnd_protocol_command * +mysqlnd_com_stmt_close_create_command(va_list args) +{ + struct st_mysqlnd_protocol_com_stmt_close_command * command; + DBG_ENTER("mysqlnd_com_stmt_close_create_command"); + command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_close_command)); + if (command) { + command->context.conn = va_arg(args, MYSQLND_CONN_DATA *); + command->context.payload = va_arg(args, MYSQLND_CSTRING); + + command->parent.free_command = mysqlnd_com_no_params_free_command; + command->parent.run = mysqlnd_com_stmt_close_run; + } + + DBG_RETURN((struct st_mysqlnd_protocol_command *) command); +} +/* }}} */ /* {{{ mysqlnd_get_command */ @@ -3847,6 +4164,27 @@ mysqlnd_get_command(enum php_mysqlnd_server_command command, ...) case COM_REAP_RESULT: ret = mysqlnd_com_reap_result_create_command(args); break; + case COM_CHANGE_USER: + ret = mysqlnd_com_change_user_create_command(args); + break; + case COM_STMT_PREPARE: + ret = mysqlnd_com_stmt_prepare_create_command(args); + break; + case COM_STMT_EXECUTE: + ret = mysqlnd_com_stmt_execute_create_command(args); + break; + case COM_STMT_FETCH: + ret = mysqlnd_com_stmt_fetch_create_command(args); + break; + case COM_STMT_RESET: + ret = mysqlnd_com_stmt_reset_create_command(args); + break; + case COM_STMT_SEND_LONG_DATA: + ret = mysqlnd_com_stmt_send_long_data_create_command(args); + break; + case COM_STMT_CLOSE: + ret = mysqlnd_com_stmt_close_create_command(args); + break; default: break; } diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h index 618845afff..831b30d13f 100644 --- a/ext/mysqlnd/mysqlnd_priv.h +++ b/ext/mysqlnd/mysqlnd_priv.h @@ -240,6 +240,11 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn, size_t * switch_to_auth_protocol_data_len ); +/* {{{ mysqlnd_get_command */ +struct st_mysqlnd_protocol_command * +mysqlnd_get_command(enum php_mysqlnd_server_command command, ...); + + #endif /* MYSQLND_PRIV_H */ diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 5d79216c97..6a94f06c47 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -417,7 +417,23 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const stmt_to_prepare = s_to_prepare->data; } - if (FAIL == stmt_to_prepare->conn->m->send_command(stmt_to_prepare->conn, COM_STMT_PREPARE, (const zend_uchar *) query, query_len, PROT_LAST, FALSE, TRUE) || + { + enum_func_status ret = FAIL; + const MYSQLND_CSTRING query_string = {query, query_len}; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_STMT_PREPARE, stmt_to_prepare->conn, query_string); + if (command) { + ret = command->run(command); + command->free_command(command); + } + if (FAIL == ret) { + goto fail; + } + } + + if ( +#if A0 + FAIL == stmt_to_prepare->conn->m->send_command(stmt_to_prepare->conn, COM_STMT_PREPARE, (const zend_uchar *) query, query_len, PROT_LAST, FALSE, TRUE) || +#endif FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare)) { goto fail; @@ -722,10 +738,19 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_ } ret = s->m->generate_execute_request(s, &request, &request_len, &free_request); if (ret == PASS) { + const MYSQLND_CSTRING payload = {request, request_len}; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_STMT_EXECUTE, stmt->conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + } +#if A0 /* support for buffer types should be added here ! */ ret = stmt->conn->m->send_command(stmt->conn, COM_STMT_EXECUTE, request, request_len, PROT_LAST /* we will handle the response packet*/, FALSE, FALSE); +#endif } else { SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM."); } @@ -1057,12 +1082,30 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f int4store(buf, stmt->stmt_id); int4store(buf + STMT_ID_LENGTH, 1); /* for now fetch only one row */ + { + const MYSQLND_CSTRING payload = {buf, sizeof(buf)}; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_STMT_FETCH, stmt->conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + if (ret == FAIL) { + COPY_CLIENT_ERROR(*stmt->error_info, *stmt->conn->error_info); + } + } + if (FAIL == ret) { + DBG_RETURN(FAIL); + } + + } +#if A9 if (FAIL == stmt->conn->m->send_command(stmt->conn, COM_STMT_FETCH, buf, sizeof(buf), PROT_LAST /* we will handle the response packet*/, FALSE, TRUE)) { COPY_CLIENT_ERROR(*stmt->error_info, *stmt->conn->error_info); DBG_RETURN(FAIL); } +#endif row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE; @@ -1263,12 +1306,30 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s) */ int4store(cmd_buf, stmt->stmt_id); + + if (CONN_GET_STATE(conn) == CONN_READY) { + const MYSQLND_CSTRING payload = {cmd_buf, sizeof(cmd_buf)}; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_STMT_RESET, stmt->conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + + if (ret == PASS) { + ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_STMT_RESET, TRUE); + } else { + COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + } + } + } +#if A0 if (CONN_GET_STATE(conn) == CONN_READY && FAIL == (ret = conn->m->send_command(conn, COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), PROT_OK_PACKET, FALSE, TRUE))) { COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); } +#endif *stmt->upsert_status = *conn->upsert_status; } DBG_INF(ret == PASS? "PASS":"FAIL"); @@ -1324,7 +1385,6 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in enum_func_status ret = FAIL; MYSQLND_CONN_DATA * conn; zend_uchar * cmd_buf; - enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA; DBG_ENTER("mysqlnd_stmt::send_long_data"); if (!stmt || !stmt->conn) { @@ -1379,11 +1439,26 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length); /* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/ - ret = conn->m->send_command(conn, cmd, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE); - mnd_efree(cmd_buf); + { + const MYSQLND_CSTRING payload = {cmd_buf, packet_len}; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_STMT_SEND_LONG_DATA, stmt->conn, payload); + ret = FAIL; + if (command) { + ret = command->run(command); + command->free_command(command); + if (ret == FAIL) { + COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + } + } + } + +#if A0 + ret = conn->m->send_command(conn, COM_STMT_SEND_LONG_DATA, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE); if (FAIL == ret) { COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); } +#endif + mnd_efree(cmd_buf); } else { ret = FAIL; SET_OOM_ERROR(*stmt->error_info); @@ -1409,7 +1484,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in #if HAVE_USLEEP && !defined(PHP_WIN32) usleep(120000); #endif - if ((packet_len = conn->net->m.consume_uneaten_data(conn->net, cmd))) { + if ((packet_len = conn->net->m.consume_uneaten_data(conn->net, COM_STMT_SEND_LONG_DATA))) { php_error_docref(NULL, E_WARNING, "There was an error " "while sending long data. Probably max_allowed_packet_size " "is smaller than the data. You have to increase it or send " @@ -2198,12 +2273,29 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo STAT_FREE_RESULT_EXPLICIT); int4store(cmd_buf, stmt->stmt_id); - if (CONN_GET_STATE(conn) == CONN_READY && + if (CONN_GET_STATE(conn) == CONN_READY) { + enum_func_status ret = FAIL; + const MYSQLND_CSTRING payload = {cmd_buf, sizeof(cmd_buf)}; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_STMT_CLOSE, conn, payload); + if (command) { + ret = command->run(command); + command->free_command(command); + + if (ret == FAIL) { + COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); + } + } + if (ret == FAIL) { + DBG_RETURN(FAIL); + } + +#if A0 FAIL == conn->m->send_command(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/, FALSE, TRUE)) { COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info); DBG_RETURN(FAIL); +#endif } } switch (stmt->execute_count) { diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index 05c5821694..9489f1d2c7 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -476,7 +476,7 @@ typedef enum_func_status (*func_mysqlnd_conn_data__free_reference)(MYSQLND_CONN_ typedef enum mysqlnd_connection_state (*func_mysqlnd_conn_data__get_state)(const MYSQLND_CONN_DATA * const conn); typedef void (*func_mysqlnd_conn_data__set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state); -typedef enum_func_status (*func_mysqlnd_conn_data__send_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status); +typedef enum_func_status (*func_mysqlnd_conn_data__send_command_do_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status); typedef enum_func_status (*func_mysqlnd_conn_data__send_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet, zend_bool silent, enum php_mysqlnd_server_command command, zend_bool ignore_upsert_status); typedef enum_func_status (*func_mysqlnd_conn_data__restart_psession)(MYSQLND_CONN_DATA * conn); @@ -501,7 +501,6 @@ typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DA typedef enum_func_status (*func_mysqlnd_conn_data__execute_init_commands)(MYSQLND_CONN_DATA * conn); typedef unsigned int (*func_mysqlnd_conn_data__get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags); typedef enum_func_status (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CONN_DATA * conn, const char * const host, const char * const user, const char * const passwd, const unsigned int passwd_len, const char * const db, const unsigned int db_len, const unsigned int mysql_flags); -typedef enum_func_status (*func_mysqlnd_conn_data__send_command_do_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status); typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const requested_protocol); typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_client_option option, const char * const key, const char * const value); @@ -572,7 +571,7 @@ struct st_mysqlnd_conn_data_methods func_mysqlnd_conn_data__get_state get_state; func_mysqlnd_conn_data__set_state set_state; - func_mysqlnd_conn_data__send_command send_command; + func_mysqlnd_conn_data__send_command_do_request send_command_do_request; func_mysqlnd_conn_data__send_command_handle_response send_command_handle_response; func_mysqlnd_conn_data__restart_psession restart_psession; @@ -597,7 +596,6 @@ struct st_mysqlnd_conn_data_methods func_mysqlnd_conn_data__execute_init_commands execute_init_commands; func_mysqlnd_conn_data__get_updated_connect_flags get_updated_connect_flags; func_mysqlnd_conn_data__connect_handshake connect_handshake; - func_mysqlnd_conn_data__send_command_do_request send_command_do_request; func_mysqlnd_conn_data__fetch_auth_plugin_by_name fetch_auth_plugin_by_name; func_mysqlnd_conn_data__set_client_option_2d set_client_option_2d; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index a67e583d05..b37ffe8dbb 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -655,12 +655,16 @@ size_t php_mysqlnd_auth_write(void * _packet) } } if (packet->is_change_user_packet) { - if (PASS != conn->m->send_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE, - PROT_LAST /* the caller will handle the OK packet */, - packet->silent, TRUE)) { - DBG_RETURN(0); + enum_func_status ret = FAIL; + const MYSQLND_CSTRING payload = {buffer + MYSQLND_HEADER_SIZE, p - (buffer + MYSQLND_HEADER_SIZE)}; + const unsigned int silent = packet->silent; + struct st_mysqlnd_protocol_command * command = mysqlnd_get_command(COM_CHANGE_USER, conn, payload, silent); + if (command) { + ret = command->run(command); + command->free_command(command); } - DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE); + + DBG_RETURN(ret == PASS? (p - buffer - MYSQLND_HEADER_SIZE) : 0); } else { size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info); if (!sent) { |