]> granicus.if.org Git - php/commitdiff
MDNR:
authorAndrey Hristov <andrey@php.net>
Thu, 29 Oct 2015 16:52:10 +0000 (17:52 +0100)
committerAndrey Hristov <andrey@php.net>
Thu, 12 Nov 2015 15:19:16 +0000 (16:19 +0100)
- make MYSQLND_UPSERT_STATUS more like an object that a simple structure
  Still use macros to make updates simple

ext/mysqlnd/mysqlnd.c
ext/mysqlnd/mysqlnd_auth.c
ext/mysqlnd/mysqlnd_driver.c
ext/mysqlnd/mysqlnd_priv.h
ext/mysqlnd/mysqlnd_ps.c
ext/mysqlnd/mysqlnd_result.c
ext/mysqlnd/mysqlnd_structs.h
ext/mysqlnd/mysqlnd_wireprotocol.c

index 8dff5505cd303f90499caf0b1cf08e6351efa521..3d2afe7779461dbf85d5c6cb8c135f4e16501f10 100644 (file)
@@ -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),
index 9512e12728edd17581a769b5a1ed8c4281b956af..7a8f848f6d8b30b3208e0bd5a682729b76eba514 100644 (file)
@@ -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);
index 00e38adde22392246e268853ee208deb0ee125b7..8c11093826e0d63e87095837ec77381a0662ee57 100644 (file)
@@ -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;
index fdd663276f4a9a3b0f512d484825c97f0c4b8038..abd475f63a86b3592159ba316c12d9e16a93ef42 100644 (file)
 
 #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);
 
index 8fa22544dc51684f4194f823da71b5c07365295a..d7bb50b4a718693d7c8a9b812ebacf429573ceba 100644 (file)
@@ -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) {
index bee0a1da88d6029ee95d0b2c34a7654977ef4c31..b06b02f22d1aa1a876d7af6e4dbc672a4346781c 100644 (file)
@@ -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;
        }
index 959c9a2cb875954b7b922a9201ab1faf2e467d6c..dae967e52c739e1d41e809b1c3216a84f76fc52f 100644 (file)
@@ -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;
index 25ed39fd4f0a69c6e3e2b7fe26ca9b2176f03dc3..da4bde11cee26e7ec4e0c848aa2434e88605dac6 100644 (file)
@@ -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);
 }