summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/mysqlnd/mysqlnd.c80
-rw-r--r--ext/mysqlnd/mysqlnd_auth.c2
-rw-r--r--ext/mysqlnd/mysqlnd_driver.c5
-rw-r--r--ext/mysqlnd/mysqlnd_priv.h5
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c25
-rw-r--r--ext/mysqlnd/mysqlnd_result.c21
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h25
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c102
8 files changed, 203 insertions, 62 deletions
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd.c
index 8dff5505cd..3d2afe7779 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd.c
@@ -44,6 +44,42 @@ PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
+/* {{{ mysqlnd_upsert_status::reset */
+void
+MYSQLND_METHOD(mysqlnd_upsert_status, reset)(MYSQLND_UPSERT_STATUS * const upsert_status)
+{
+ upsert_status->warning_count = 0;
+ upsert_status->server_status = 0;
+ upsert_status->affected_rows = 0;
+ upsert_status->last_insert_id = 0;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_upsert_status::set_affected_rows_to_error */
+void
+MYSQLND_METHOD(mysqlnd_upsert_status, set_affected_rows_to_error)(MYSQLND_UPSERT_STATUS * upsert_status)
+{
+ upsert_status->affected_rows = (uint64_t) ~0;
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_upsert_status)
+ MYSQLND_METHOD(mysqlnd_upsert_status, reset),
+ MYSQLND_METHOD(mysqlnd_upsert_status, set_affected_rows_to_error),
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ mysqlnd_upsert_status_init */
+void
+mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status)
+{
+ upsert_status->m = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_upsert_status);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn_data::free_options */
static void
MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn)
@@ -190,9 +226,12 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn)
/* {{{ mysqlnd_conn_data::send_command_handle_response */
static enum_func_status
-MYSQLND_METHOD(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)
+MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(
+ MYSQLND_CONN_DATA * const conn,
+ const enum mysqlnd_packet_type ok_packet,
+ const zend_bool silent,
+ const enum php_mysqlnd_server_command command,
+ const zend_bool ignore_upsert_status)
{
enum_func_status ret = FAIL;
@@ -228,14 +267,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(MYSQLND_CONN_DAT
safe to unconditionally turn off the flag here.
*/
conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
} else {
SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
ok_response->message, ok_response->message_len,
conn->persistent);
if (!ignore_upsert_status) {
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
conn->upsert_status->warning_count = ok_response->warning_count;
conn->upsert_status->server_status = ok_response->server_status;
conn->upsert_status->affected_rows = ok_response->affected_rows;
@@ -263,7 +302,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(MYSQLND_CONN_DAT
} else if (0xFF == ok_response->field_count) {
/* The server signalled error. Set the error */
SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
} else if (0xFE != ok_response->field_count) {
SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
if (!silent) {
@@ -288,10 +327,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(MYSQLND_CONN_DAT
/* }}} */
-/* {{{ mysqlnd_conn_data::simple_command_send_request */
+/* {{{ mysqlnd_conn_data::send_command_do_request */
static enum_func_status
-MYSQLND_METHOD(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)
+MYSQLND_METHOD(mysqlnd_conn_data, send_command_do_request)(
+ MYSQLND_CONN_DATA * const conn,
+ const enum php_mysqlnd_server_command command,
+ const zend_uchar * const arg, const size_t arg_len,
+ const zend_bool silent,
+ const zend_bool ignore_upsert_status)
{
enum_func_status ret = PASS;
MYSQLND_PACKET_COMMAND * cmd_packet;
@@ -314,7 +357,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_command_do_request)(MYSQLND_CONN_DATA * c
DBG_RETURN(FAIL);
}
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
SET_EMPTY_ERROR(*conn->error_info);
cmd_packet = conn->payload_decoder_factory->m.get_command_packet(conn->payload_decoder_factory, FALSE);
@@ -747,7 +790,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
{
goto err;
}
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+
+ UPSERT_STATUS_RESET(conn->upsert_status);
conn->upsert_status->warning_count = 0;
conn->upsert_status->server_status = greet_packet->server_status;
conn->upsert_status->affected_rows = 0;
@@ -791,7 +835,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
local_tx_started = TRUE;
SET_EMPTY_ERROR(*conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u persistent=%u state=%u",
host?host:"", user?user:"", db?db:"", port, mysql_flags,
@@ -1595,7 +1639,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, con
The server sends 0 but libmysql doesn't read it and has established
a protocol of giving back -1. Thus we have to follow it :(
*/
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
if (ret == PASS) {
if (conn->connect_or_select_db) {
mnd_pefree(conn->connect_or_select_db, conn->persistent);
@@ -1635,7 +1679,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn)
The server sends 0 but libmysql doesn't read it and has established
a protocol of giving back -1. Thus we have to follow it :(
*/
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
conn->m->local_tx_end(conn, this_func, ret);
}
@@ -1711,7 +1755,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int p
The server sends 0 but libmysql doesn't read it and has established
a protocol of giving back -1. Thus we have to follow it :(
*/
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
} else if (PASS == ret) {
CONN_SET_STATE(conn, CONN_QUIT_SENT);
conn->m->send_close(conn);
@@ -2095,7 +2139,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn)
}
SET_EMPTY_ERROR(*conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
/*
We are sure that there is a result set, since conn->state is set accordingly
in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
@@ -2202,7 +2246,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
}
SET_EMPTY_ERROR(*conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
if (!user) {
user = "";
@@ -2961,7 +3005,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_do_request),
+// 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),
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index 9512e12728..7a8f848f6d 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -289,7 +289,7 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
mnd_pefree(conn->last_message, conn->persistent);
conn->last_message = NULL;
}
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
/* set charset for old servers */
if (conn->m->get_server_version(conn) < 50123) {
ret = conn->m->set_charset(conn, old_cs->name);
diff --git a/ext/mysqlnd/mysqlnd_driver.c b/ext/mysqlnd/mysqlnd_driver.c
index 00e38adde2..8c11093826 100644
--- a/ext/mysqlnd/mysqlnd_driver.c
+++ b/ext/mysqlnd/mysqlnd_driver.c
@@ -135,7 +135,10 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(struct st_mysqlnd_object_
data->error_info = &(data->error_info_impl);
data->options = &(data->options_impl);
+
+ mysqlnd_upsert_status_init(&data->upsert_status_impl);
data->upsert_status = &(data->upsert_status_impl);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(data->upsert_status);
data->persistent = persistent;
data->m = mysqlnd_conn_data_get_methods();
@@ -151,7 +154,6 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(struct st_mysqlnd_object_
zend_llist_init(data->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t)mysqlnd_error_list_pdtor, persistent);
mysqlnd_stats_init(&data->stats, STAT_LAST, persistent);
- SET_ERROR_AFF_ROWS(data);
data->net = mysqlnd_net_init(persistent, data->stats, data->error_info);
data->payload_decoder_factory = mysqlnd_protocol_payload_decoder_factory_init(data, persistent);
@@ -219,6 +221,7 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA
}
stmt->persistent = persistent;
stmt->error_info = &(stmt->error_info_impl);
+ mysqlnd_upsert_status_init(&stmt->upsert_status_impl);
stmt->upsert_status = &(stmt->upsert_status_impl);
stmt->state = MYSQLND_STMT_INITTED;
stmt->execute_cmd_buffer.length = 4096;
diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h
index fdd663276f..abd475f63a 100644
--- a/ext/mysqlnd/mysqlnd_priv.h
+++ b/ext/mysqlnd/mysqlnd_priv.h
@@ -76,8 +76,10 @@
#define MAX_CHARSET_LEN 32
+void mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status);
-#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status->affected_rows = (uint64_t) ~0
+#define UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(status) (status)->m->set_affected_rows_to_error((status))
+#define UPSERT_STATUS_RESET(status) (status)->m->reset((status))
/* Error handling */
#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \
@@ -181,6 +183,7 @@ PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_result_unbuffered)
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_result_buffered);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol_payload_decoder_factory);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net);
+PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_upsert_status);
enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning);
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 8fa22544dc..d7bb50b4a7 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -358,6 +358,11 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s)
if (stmt->result) {
stmt->result->m.free_result_contents(stmt->result);
mnd_efree(stmt->result);
+ /* XXX: This will crash, because we will null also the methods.
+ But seems it happens in extreme cases or doesn't. Should be fixed by exporting a function
+ (from mysqlnd_driver.c?) to do the reset.
+ This is done also in mysqlnd_result.c
+ */
memset(stmt, 0, sizeof(MYSQLND_STMT_DATA));
stmt->state = MYSQLND_STMT_INITTED;
}
@@ -389,8 +394,8 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
DBG_INF_FMT("query=%s", query);
- SET_ERROR_AFF_ROWS(stmt);
- SET_ERROR_AFF_ROWS(stmt->conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->upsert_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->conn->upsert_status);
SET_EMPTY_ERROR(*stmt->error_info);
SET_EMPTY_ERROR(*stmt->conn->error_info);
@@ -516,7 +521,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
ret = stmt->conn->m->query_read_result_set_header(stmt->conn, s);
if (ret == FAIL) {
COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
- memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status));
+ UPSERT_STATUS_RESET(stmt->upsert_status);
stmt->upsert_status->affected_rows = conn->upsert_status->affected_rows;
if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
/* close the statement here, the connection has been closed */
@@ -650,8 +655,8 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
conn = stmt->conn;
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- SET_ERROR_AFF_ROWS(stmt);
- SET_ERROR_AFF_ROWS(stmt->conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->upsert_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->conn->upsert_status);
if (stmt->result && stmt->state >= MYSQLND_STMT_PREPARED && stmt->field_count) {
/*
@@ -733,7 +738,7 @@ 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};
+ const MYSQLND_CSTRING payload = {(const char*) request, request_len};
struct st_mysqlnd_protocol_command * command = stmt->conn->command_factory(COM_STMT_EXECUTE, stmt->conn, payload);
ret = FAIL;
if (command) {
@@ -970,7 +975,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
DBG_INF("EOF");
/* Mark the connection as usable again */
result->unbuf->eof_reached = TRUE;
- memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
+ UPSERT_STATUS_RESET(result->conn->upsert_status);
result->conn->upsert_status->warning_count = row_packet->warning_count;
result->conn->upsert_status->server_status = row_packet->server_status;
/*
@@ -1070,7 +1075,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
int4store(buf + MYSQLND_STMT_ID_LENGTH, 1); /* for now fetch only one row */
{
- const MYSQLND_CSTRING payload = {buf, sizeof(buf)};
+ const MYSQLND_CSTRING payload = {(const char*) buf, sizeof(buf)};
struct st_mysqlnd_protocol_command * command = stmt->conn->command_factory(COM_STMT_FETCH, stmt->conn, payload);
ret = FAIL;
if (command) {
@@ -1096,7 +1101,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE;
- memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status));
+ UPSERT_STATUS_RESET(stmt->upsert_status);
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
const MYSQLND_RES_METADATA * const meta = result->meta;
unsigned int i, field_count = result->field_count;
@@ -1416,7 +1421,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
/* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/
{
- const MYSQLND_CSTRING payload = {cmd_buf, packet_len};
+ const MYSQLND_CSTRING payload = {(const char *) cmd_buf, packet_len};
struct st_mysqlnd_protocol_command * command = stmt->conn->command_factory(COM_STMT_SEND_LONG_DATA, stmt->conn, payload);
ret = FAIL;
if (command) {
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index bee0a1da88..b06b02f22d 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -418,7 +418,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
break;
}
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
if (FAIL == (ret = PACKET_READ(rset_header, conn))) {
php_error_docref(NULL, E_WARNING, "Error reading result set's header");
@@ -465,7 +465,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
DBG_INF("UPSERT");
conn->last_query_type = QUERY_UPSERT;
conn->field_count = rset_header->field_count;
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
conn->upsert_status->warning_count = rset_header->warning_count;
conn->upsert_status->server_status = rset_header->server_status;
conn->upsert_status->affected_rows = rset_header->affected_rows;
@@ -490,9 +490,9 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_RSET_QUERY);
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
/* restore after zeroing */
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
conn->last_query_type = QUERY_SELECT;
CONN_SET_STATE(conn, CONN_FETCHING_DATA);
@@ -556,6 +556,11 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
conn->current_result = NULL;
} else {
stmt->result = NULL;
+ /* XXX: This will crash, because we will null also the methods.
+ But seems it happens in extreme cases or doesn't. Should be fixed by exporting a function
+ (from mysqlnd_driver.c?) to do the reset.
+ This is done also in mysqlnd_ps.c
+ */
memset(stmt, 0, sizeof(*stmt));
stmt->state = MYSQLND_STMT_INITTED;
}
@@ -772,7 +777,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
/* Mark the connection as usable again */
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
+
+ UPSERT_STATUS_RESET(result->conn->upsert_status);
result->conn->upsert_status->warning_count = row_packet->warning_count;
result->conn->upsert_status->server_status = row_packet->server_status;
/*
@@ -898,7 +904,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
/* Mark the connection as usable again */
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
+
+ UPSERT_STATUS_RESET(result->conn->upsert_status);
result->conn->upsert_status->warning_count = row_packet->warning_count;
result->conn->upsert_status->server_status = row_packet->server_status;
/*
@@ -1354,7 +1361,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
/* Finally clean */
if (row_packet->eof) {
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
conn->upsert_status->warning_count = row_packet->warning_count;
conn->upsert_status->server_status = row_packet->server_status;
}
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index 959c9a2cb8..dae967e52c 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -28,7 +28,8 @@
#define MYSQLND_TYPEDEFED_METHODS
#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
-#define MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class)
+#define MYSQLND_CLASS_METHOD_TABLE_NAME_DECL(class) struct st_##class##_methods
+#define MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) MYSQLND_CLASS_METHOD_TABLE_NAME_DECL(class) MYSQLND_CLASS_METHOD_TABLE_NAME(class)
#define MYSQLND_CLASS_METHODS_START(class) MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) = {
#define MYSQLND_CLASS_METHODS_END }
@@ -98,13 +99,25 @@ typedef struct st_mysqlnd_field
} MYSQLND_FIELD;
-typedef struct st_mysqlnd_upsert_result
+typedef struct st_mysqlnd_upsert_status MYSQLND_UPSERT_STATUS;
+typedef void (*func_mysqlnd_upsert_status__reset)(MYSQLND_UPSERT_STATUS * const upsert_status);
+typedef void (*func_mysqlnd_upsert_status__set_affected_rows_to_error)(MYSQLND_UPSERT_STATUS * const upsert_status);
+
+MYSQLND_CLASS_METHOD_TABLE_NAME_DECL(mysqlnd_upsert_status)
+{
+ func_mysqlnd_upsert_status__reset reset;
+ func_mysqlnd_upsert_status__set_affected_rows_to_error set_affected_rows_to_error;
+};
+
+struct st_mysqlnd_upsert_status
{
unsigned int warning_count;
unsigned int server_status;
uint64_t affected_rows;
uint64_t last_insert_id;
-} MYSQLND_UPSERT_STATUS;
+
+ struct st_mysqlnd_upsert_status_methods *m;
+};
typedef struct st_mysqlnd_error_info
@@ -476,8 +489,8 @@ 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_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__send_command_do_request)(MYSQLND_CONN_DATA * const conn, const enum php_mysqlnd_server_command command, const zend_uchar * const arg, const size_t arg_len, const zend_bool silent, const zend_bool ignore_upsert_status);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_command_handle_response)(MYSQLND_CONN_DATA * const conn, const enum mysqlnd_packet_type ok_packet, const zend_bool silent, const enum php_mysqlnd_server_command command, const zend_bool ignore_upsert_status);
typedef enum_func_status (*func_mysqlnd_conn_data__restart_psession)(MYSQLND_CONN_DATA * conn);
typedef enum_func_status (*func_mysqlnd_conn_data__end_psession)(MYSQLND_CONN_DATA * conn);
@@ -571,7 +584,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_do_request send_command_do_request;
+// 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;
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index 25ed39fd4f..da4bde11ce 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -2660,6 +2660,72 @@ mysqlnd_protocol_payload_decoder_factory_free(MYSQLND_PROTOCOL_PAYLOAD_DECODER_F
+/* {{{ mysqlnd_conn_data::send_command_do_request */
+static enum_func_status
+send_command_do_request(
+ MYSQLND_CONN_DATA * const conn,
+ const enum php_mysqlnd_server_command command,
+ const zend_uchar * const arg, const size_t arg_len,
+ const zend_bool silent,
+ const zend_bool ignore_upsert_status)
+{
+ enum_func_status ret = PASS;
+ MYSQLND_PACKET_COMMAND * cmd_packet = NULL;
+ enum mysqlnd_connection_state conn_state = CONN_GET_STATE(conn);
+ MYSQLND_ERROR_INFO * error_info = conn->error_info;
+ DBG_ENTER("mysqlnd_conn_data::send_command_do_request");
+ DBG_INF_FMT("command=%s silent=%u", mysqlnd_command_to_text[command], silent);
+ DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
+ DBG_INF_FMT("sending %u bytes", arg_len + 1); /* + 1 is for the command */
+
+ switch (conn_state) {
+ case CONN_READY:
+ break;
+ case CONN_QUIT_SENT:
+ SET_CLIENT_ERROR(*error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ DBG_ERR("Server is gone");
+ DBG_RETURN(FAIL);
+ default:
+ SET_CLIENT_ERROR(*error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ DBG_ERR_FMT("Command out of sync. State=%u", conn_state);
+ DBG_RETURN(FAIL);
+ }
+
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
+ SET_EMPTY_ERROR(*conn->error_info);
+
+ cmd_packet = conn->payload_decoder_factory->m.get_command_packet(conn->payload_decoder_factory, FALSE);
+ if (!cmd_packet) {
+ SET_OOM_ERROR(*conn->error_info);
+ DBG_RETURN(FAIL);
+ }
+
+ cmd_packet->command = command;
+ if (arg && arg_len) {
+ cmd_packet->argument = arg;
+ cmd_packet->arg_len = arg_len;
+ }
+
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_COM_QUIT + command - 1 /* because of COM_SLEEP */ );
+
+ if (! PACKET_WRITE(cmd_packet, conn)) {
+ if (!silent) {
+ DBG_ERR_FMT("Error while sending %s packet", mysqlnd_command_to_text[command]);
+ php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid());
+ }
+ CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ conn->m->send_close(conn);
+ DBG_ERR("Server is gone");
+ ret = FAIL;
+ }
+ PACKET_FREE(cmd_packet);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+
+
struct st_mysqlnd_protocol_no_params_command
{
@@ -2706,7 +2772,7 @@ mysqlnd_com_set_option_run(void *cmd)
DBG_ENTER("mysqlnd_com_set_option_run");
int2store(buffer, (unsigned int) option);
- ret = conn->m->send_command_do_request(conn, COM_SET_OPTION, buffer, sizeof(buffer), FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_SET_OPTION, buffer, sizeof(buffer), FALSE, TRUE);
if (PASS == ret) {
ret = conn->m->send_command_handle_response(conn, PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE);
}
@@ -2747,7 +2813,7 @@ mysqlnd_com_debug_run(void *cmd)
DBG_ENTER("mysqlnd_com_debug_run");
- ret = conn->m->send_command_do_request(conn, COM_DEBUG, NULL, 0, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_DEBUG, NULL, 0, FALSE, TRUE);
if (PASS == ret) {
ret = conn->m->send_command_handle_response(conn, PROT_EOF_PACKET, COM_DEBUG, COM_DEBUG, TRUE);
}
@@ -2798,7 +2864,7 @@ mysqlnd_com_init_db_run(void *cmd)
DBG_ENTER("mysqlnd_com_init_db_run");
- ret = conn->m->send_command_do_request(conn, COM_INIT_DB, (zend_uchar*) command->context.db.s, command->context.db.l, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_INIT_DB, (zend_uchar*) command->context.db.s, command->context.db.l, FALSE, TRUE);
if (PASS == ret) {
ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_INIT_DB, TRUE);
}
@@ -2839,7 +2905,7 @@ mysqlnd_com_ping_run(void *cmd)
DBG_ENTER("mysqlnd_com_ping_run");
- ret = conn->m->send_command_do_request(conn, COM_PING, NULL, 0, TRUE, TRUE);
+ ret = send_command_do_request(conn, COM_PING, NULL, 0, TRUE, TRUE);
if (PASS == ret) {
ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, TRUE, COM_PING, TRUE);
}
@@ -2906,7 +2972,7 @@ mysqlnd_com_field_list_run(void *cmd)
*p++ = '\0';
}
- ret = conn->m->send_command_do_request(conn, COM_FIELD_LIST, buff, p - buff, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_FIELD_LIST, buff, p - buff, FALSE, TRUE);
DBG_RETURN(ret);
}
@@ -2945,7 +3011,7 @@ mysqlnd_com_statistics_run(void *cmd)
DBG_ENTER("mysqlnd_com_statistics_run");
- ret = conn->m->send_command_do_request(conn, COM_STATISTICS, NULL, 0, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_STATISTICS, NULL, 0, FALSE, TRUE);
DBG_RETURN(ret);
}
@@ -2995,7 +3061,7 @@ mysqlnd_com_process_kill_run(void *cmd)
DBG_ENTER("mysqlnd_com_process_kill_run");
int4store(buff, command->context.process_id);
- ret = conn->m->send_command_do_request(conn, COM_PROCESS_KILL, buff, 4, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_PROCESS_KILL, buff, 4, FALSE, TRUE);
if (PASS == ret && command->context.read_response) {
ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_PROCESS_KILL, TRUE);
}
@@ -3049,7 +3115,7 @@ mysqlnd_com_refresh_run(void *cmd)
DBG_ENTER("mysqlnd_com_refresh_run");
int1store(bits, command->context.options);
- ret = conn->m->send_command_do_request(conn, COM_REFRESH, bits, 1, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_REFRESH, bits, 1, FALSE, TRUE);
if (PASS == ret) {
ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_REFRESH, TRUE);
}
@@ -3103,7 +3169,7 @@ mysqlnd_com_shutdown_run(void *cmd)
DBG_ENTER("mysqlnd_com_shutdown_run");
int1store(bits, command->context.level);
- ret = conn->m->send_command_do_request(conn, COM_SHUTDOWN, bits, 1, FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_SHUTDOWN, bits, 1, FALSE, TRUE);
if (PASS == ret) {
ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_SHUTDOWN, TRUE);
}
@@ -3154,7 +3220,7 @@ mysqlnd_com_quit_run(void *cmd)
DBG_ENTER("mysqlnd_com_quit_run");
- ret = conn->m->send_command_do_request(conn, COM_QUIT, NULL, 0, TRUE, TRUE);
+ ret = send_command_do_request(conn, COM_QUIT, NULL, 0, TRUE, TRUE);
DBG_RETURN(ret);
}
@@ -3201,7 +3267,7 @@ mysqlnd_com_query_run(void *cmd)
DBG_ENTER("mysqlnd_com_query_run");
- ret = conn->m->send_command_do_request(conn, COM_QUERY, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE, FALSE);
+ ret = send_command_do_request(conn, COM_QUERY, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE, FALSE);
if (PASS == ret) {
CONN_SET_STATE(conn, CONN_QUERY_SENT);
@@ -3254,7 +3320,7 @@ mysqlnd_com_change_user_run(void *cmd)
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);
+ ret = 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);
}
@@ -3356,7 +3422,7 @@ mysqlnd_com_stmt_prepare_run(void *cmd)
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);
+ ret = send_command_do_request(conn, COM_STMT_PREPARE, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE, TRUE);
DBG_RETURN(ret);
}
@@ -3405,7 +3471,7 @@ mysqlnd_com_stmt_execute_run(void *cmd)
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);
+ ret = send_command_do_request(conn, COM_STMT_EXECUTE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, FALSE);
DBG_RETURN(ret);
}
@@ -3454,7 +3520,7 @@ mysqlnd_com_stmt_fetch_run(void *cmd)
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);
+ ret = send_command_do_request(conn, COM_STMT_FETCH, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE, TRUE);
DBG_RETURN(ret);
}
@@ -3505,7 +3571,7 @@ mysqlnd_com_stmt_reset_run(void *cmd)
DBG_ENTER("mysqlnd_com_stmt_reset_run");
int4store(cmd_buf, command->context.stmt_id);
- ret = conn->m->send_command_do_request(conn, COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), FALSE, TRUE);
DBG_RETURN(ret);
}
@@ -3554,7 +3620,7 @@ mysqlnd_com_stmt_send_long_data_run(void *cmd)
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);
+ ret = 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);
}
@@ -3605,7 +3671,7 @@ mysqlnd_com_stmt_close_run(void *cmd)
DBG_ENTER("mysqlnd_com_stmt_close_run");
int4store(cmd_buf, command->context.stmt_id);
- ret = conn->m->send_command_do_request(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), FALSE, TRUE);
+ ret = send_command_do_request(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), FALSE, TRUE);
DBG_RETURN(ret);
}