]> granicus.if.org Git - php/commitdiff
MNDR:
authorAndrey Hristov <andrey@php.net>
Fri, 30 Oct 2015 15:05:55 +0000 (16:05 +0100)
committerAndrey Hristov <andrey@php.net>
Thu, 12 Nov 2015 15:19:16 +0000 (16:19 +0100)
- now send_command_handle_response() also doesn't depend directly on
  MYSQLND_CONN_DATA

ext/mysqlnd/mysqlnd.c
ext/mysqlnd/mysqlnd_auth.c
ext/mysqlnd/mysqlnd_loaddata.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
ext/mysqlnd/mysqlnd_wireprotocol.h

index 15f399956c2928006d81905966ebe357dff737b2..fd41cd4bb1d0da276cc5e930625e8932c302a214 100644 (file)
@@ -309,9 +309,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn)
                mnd_pefree(conn->auth_plugin_data, pers);
                conn->auth_plugin_data = NULL;
        }
-       if (conn->last_message) {
-               mnd_pefree(conn->last_message, pers);
-               conn->last_message = NULL;
+       if (conn->last_message.s) {
+               mnd_pefree(conn->last_message.s, pers);
+               conn->last_message.s = NULL;
        }
        if (conn->error_info->error_list) {
                zend_llist_clean(conn->error_info->error_list);
@@ -356,7 +356,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn)
 }
 /* }}} */
 
-
+#if 0
 /* {{{ mysqlnd_conn_data::send_command_handle_response */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(
@@ -458,7 +458,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response)(
        DBG_RETURN(ret);
 }
 /* }}} */
-
+#endif
 
 /* {{{ mysqlnd_conn_data::set_server_option */
 static enum_func_status
@@ -488,9 +488,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, restart_psession)(MYSQLND_CONN_DATA * conn)
        DBG_ENTER("mysqlnd_conn_data::restart_psession");
        MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_REUSED);
        /* Free here what should not be seen by the next script */
-       if (conn->last_message) {
-               mnd_pefree(conn->last_message, conn->persistent);
-               conn->last_message = NULL;
+       if (conn->last_message.s) {
+               mnd_pefree(conn->last_message.s, conn->persistent);
+               conn->last_message.s = NULL;
        }
        DBG_RETURN(PASS);
 }
@@ -1791,7 +1791,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, zend_stri
 
                        if (PASS == (ret = PACKET_READ(stats_header))) {
                                /* will be freed by Zend, thus don't use the mnd_ allocator */
-                               *message = zend_string_init(stats_header->message, stats_header->message_len, 0);
+                               *message = zend_string_init(stats_header->message.s, stats_header->message.l, 0);
                                DBG_INF(ZSTR_VAL(*message));
                        }
                        PACKET_FREE(stats_header);
@@ -2075,7 +2075,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, warning_count)(const MYSQLND_CONN_DATA * const
 static const char *
 MYSQLND_METHOD(mysqlnd_conn_data, info)(const MYSQLND_CONN_DATA * const conn)
 {
-       return conn->last_message;
+       return conn->last_message.s;
 }
 /* }}} */
 
@@ -3054,7 +3054,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
        MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_reference),
        MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference),
 
-       MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response),
+//     MYSQLND_METHOD(mysqlnd_conn_data, send_command_handle_response),
        MYSQLND_METHOD(mysqlnd_conn_data, restart_psession),
        MYSQLND_METHOD(mysqlnd_conn_data, end_psession),
        MYSQLND_METHOD(mysqlnd_conn_data, send_close),
index c95238035010dfb27966e6a5a065a6b31148f2a4..814a06bd2aefb8f3279758338ad03abe82f1c259 100644 (file)
@@ -139,7 +139,7 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
                goto end;
        }
 
-       SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, auth_resp_packet->message, auth_resp_packet->message_len, conn->persistent);
+       SET_NEW_MESSAGE(conn->last_message.s, conn->last_message.l, auth_resp_packet->message, auth_resp_packet->message_len, conn->persistent);
        ret = PASS;
 end:
        PACKET_FREE(change_auth_resp_packet);
@@ -285,9 +285,9 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
                }
                conn->passwd = tmp;
 
-               if (conn->last_message) {
-                       mnd_pefree(conn->last_message, conn->persistent);
-                       conn->last_message = NULL;
+               if (conn->last_message.s) {
+                       mnd_pefree(conn->last_message.s, conn->persistent);
+                       conn->last_message.s = NULL;
                }
                UPSERT_STATUS_RESET(conn->upsert_status);
                /* set charset for old servers */
index b3f4140474cc4d84d31ce48b99c4cb68b4c8c2b5..b43607443e8d2739c4392103014be0c07388b8f9 100644 (file)
@@ -141,7 +141,7 @@ static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA
 
 /* {{{ mysqlnd_handle_local_infile */
 enum_func_status
-mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning)
+mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filename, zend_bool * is_warning)
 {
        zend_uchar                      *buf = NULL;
        zend_uchar                      empty_packet[MYSQLND_HEADER_SIZE];
@@ -212,7 +212,8 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen
 
 infile_error:
        /* get response from server and update upsert values */
-       if (FAIL == conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE)) {
+       if (FAIL == send_command_handle_response(PROT_OK_PACKET, FALSE, COM_QUERY, FALSE,
+                                                conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent)) {
                result = FAIL;
        }
 
index d9583b4be70d9888e4a1b0c3c4ba7e79cce2277e..0451812fd0c2b0c360e4f4a8ae176dfb8eb0a79d 100644 (file)
@@ -149,7 +149,7 @@ PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net);
 PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_upsert_status);
 PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_error_info);
 
-enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning);
+enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filename, zend_bool * is_warning);
 
 
 
@@ -209,6 +209,20 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
 
 extern func_mysqlnd__command_factory mysqlnd_command_factory;
 
+
+enum_func_status
+send_command_handle_response(
+               const enum mysqlnd_packet_type ok_packet,
+               const zend_bool silent,
+               const enum php_mysqlnd_server_command command,
+               const zend_bool ignore_upsert_status,
+
+               MYSQLND_ERROR_INFO      * error_info,
+               MYSQLND_UPSERT_STATUS * upsert_status,
+               MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory,
+               MYSQLND_STRING * last_message,
+               zend_bool last_message_persistent
+       );
 #endif /* MYSQLND_PRIV_H */
 
 
index 59f600a2ee999443153ef9a39d59f5529642c757..bc68816ce0ca271a6a83b1d54041bf41015c7fc6 100644 (file)
@@ -1302,9 +1302,7 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s)
                                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 {
+                               if (ret == FAIL) {
                                        COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
                                }
                        }
index 19b302e08df7561c48a80cbf7b73232cb77003e6..27a463f1ebae73719e15eba8bb06640fa426017f 100644 (file)
@@ -456,7 +456,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
                                conn->last_query_type = QUERY_LOAD_LOCAL;
                                conn->field_count = 0; /* overwrite previous value, or the last value could be used and lead to bug#53503 */
                                SET_CONNECTION_STATE(&conn->state, CONN_SENDING_LOAD_DATA);
-                               ret = mysqlnd_handle_local_infile(conn, rset_header->info_or_local_file, &is_warning);
+                               ret = mysqlnd_handle_local_infile(conn, rset_header->info_or_local_file.s, &is_warning);
                                SET_CONNECTION_STATE(&conn->state,  (ret == PASS || is_warning == TRUE)? CONN_READY:CONN_QUIT_SENT);
                                MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY);
                                break;
@@ -470,8 +470,8 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
                                conn->upsert_status->server_status = rset_header->server_status;
                                conn->upsert_status->affected_rows = rset_header->affected_rows;
                                conn->upsert_status->last_insert_id = rset_header->last_insert_id;
-                               SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
-                                                               rset_header->info_or_local_file, rset_header->info_or_local_file_len,
+                               SET_NEW_MESSAGE(conn->last_message.s, conn->last_message.l,
+                                                               rset_header->info_or_local_file.s, rset_header->info_or_local_file.l,
                                                                conn->persistent);
                                /* Result set can follow UPSERT statement, check server_status */
                                if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
@@ -487,7 +487,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
                                enum_mysqlnd_collected_stats statistic = STAT_LAST;
 
                                DBG_INF("Result set pending");
-                               SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
+                               SET_EMPTY_MESSAGE(conn->last_message.s, conn->last_message.l, conn->persistent);
 
                                MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_RSET_QUERY);
                                UPSERT_STATUS_RESET(conn->upsert_status);
index e099c1bea2210ab92820605387aaad86c0f2803f..f1db6f424df5038534a27a31e5324579670d1be8 100644 (file)
 #define MYSQLND_CLASS_METHODS_END                      }
 
 
+typedef struct st_mysqlnd_string
+{
+       char    *s;
+       size_t  l;
+} MYSQLND_STRING;
+
+typedef struct st_mysqlnd_const_string
+{
+       const char *s;
+       size_t  l;
+} MYSQLND_CSTRING;
+
+
 typedef struct st_mysqlnd_memory_pool MYSQLND_MEMORY_POOL;
 typedef struct st_mysqlnd_memory_pool_chunk MYSQLND_MEMORY_POOL_CHUNK;
 typedef struct st_mysqlnd_memory_pool_chunk_llist MYSQLND_MEMORY_POOL_CHUNK_LLIST;
@@ -594,7 +607,7 @@ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data)
        func_mysqlnd_conn_data__get_reference get_reference;
        func_mysqlnd_conn_data__free_reference free_reference;
 
-       func_mysqlnd_conn_data__send_command_handle_response send_command_handle_response;
+//     func_mysqlnd_conn_data__send_command_handle_response send_command_handle_response;
 
        func_mysqlnd_conn_data__restart_psession restart_psession;
        func_mysqlnd_conn_data__end_psession end_psession;
@@ -985,8 +998,7 @@ struct st_mysqlnd_connection_data
        /* For UPSERT queries */
        MYSQLND_UPSERT_STATUS * upsert_status;
        MYSQLND_UPSERT_STATUS upsert_status_impl;
-       char                    *last_message;
-       unsigned int    last_message_len;
+       MYSQLND_STRING last_message;
 
        /* If error packet, we use these */
        MYSQLND_ERROR_INFO      * error_info;
@@ -1221,19 +1233,6 @@ struct st_mysqlnd_stmt
 };
 
 
-typedef struct st_mysqlnd_string
-{
-       char    *s;
-       size_t  l;
-} MYSQLND_STRING;
-
-typedef struct st_mysqlnd_const_string
-{
-       const char *s;
-       size_t  l;
-} MYSQLND_CSTRING;
-
-
 struct st_mysqlnd_plugin_header
 {
        unsigned int    plugin_api_version;
index cf46e8c84b312b6b4b192d9d151e1c2731b6f83c..21508614eda0520670453be3da088b0c720ca2c2 100644 (file)
@@ -1060,13 +1060,13 @@ size_t php_mysqlnd_cmd_write(void * _packet)
        net->data->m.consume_uneaten_data(net, packet->command);
 #endif
 
-       if (!packet->argument || !packet->arg_len) {
+       if (!packet->argument.s || !packet->argument.l) {
                zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
 
                int1store(buffer + MYSQLND_HEADER_SIZE, packet->command);
                sent = net->data->m.send_ex(net, buffer, 1, conn->stats, conn->error_info);
        } else {
-               size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE;
+               size_t tmp_len = packet->argument.l + 1 + MYSQLND_HEADER_SIZE;
                zend_uchar *tmp, *p;
                tmp = (tmp_len > net->cmd_buffer.length)? mnd_emalloc(tmp_len):net->cmd_buffer.buffer;
                if (!tmp) {
@@ -1077,7 +1077,7 @@ size_t php_mysqlnd_cmd_write(void * _packet)
                int1store(p, packet->command);
                p++;
 
-               memcpy(p, packet->argument, packet->arg_len);
+               memcpy(p, packet->argument.s, packet->argument.l);
 
                sent = net->data->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
                if (tmp != net->cmd_buffer.buffer) {
@@ -1161,11 +1161,11 @@ php_mysqlnd_rset_header_read(void * _packet)
                          would lead to 0 byte allocation but 2^32 or 2^64 bytes copied.
                        */
                        len = packet->header.size - 1;
-                       packet->info_or_local_file = mnd_emalloc(len + 1);
-                       if (packet->info_or_local_file) {
-                               memcpy(packet->info_or_local_file, p, len);
-                               packet->info_or_local_file[len] = '\0';
-                               packet->info_or_local_file_len = len;
+                       packet->info_or_local_file.s = mnd_emalloc(len + 1);
+                       if (packet->info_or_local_file.s) {
+                               memcpy(packet->info_or_local_file.s, p, len);
+                               packet->info_or_local_file.s[len] = '\0';
+                               packet->info_or_local_file.l = len;
                        } else {
                                SET_OOM_ERROR(conn->error_info);
                                ret = FAIL;
@@ -1188,11 +1188,11 @@ php_mysqlnd_rset_header_read(void * _packet)
                        BAIL_IF_NO_MORE_DATA;
                        /* Check for additional textual data */
                        if (packet->header.size  > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) {
-                               packet->info_or_local_file = mnd_emalloc(len + 1);
-                               if (packet->info_or_local_file) {
-                                       memcpy(packet->info_or_local_file, p, len);
-                                       packet->info_or_local_file[len] = '\0';
-                                       packet->info_or_local_file_len = len;
+                               packet->info_or_local_file.s = mnd_emalloc(len + 1);
+                               if (packet->info_or_local_file.s) {
+                                       memcpy(packet->info_or_local_file.s, p, len);
+                                       packet->info_or_local_file.s[len] = '\0';
+                                       packet->info_or_local_file.l = len;
                                } else {
                                        SET_OOM_ERROR(conn->error_info);
                                        ret = FAIL;
@@ -1225,9 +1225,9 @@ void php_mysqlnd_rset_header_free_mem(void * _packet, zend_bool stack_allocation
 {
        MYSQLND_PACKET_RSET_HEADER *p= (MYSQLND_PACKET_RSET_HEADER *) _packet;
        DBG_ENTER("php_mysqlnd_rset_header_free_mem");
-       if (p->info_or_local_file) {
-               mnd_efree(p->info_or_local_file);
-               p->info_or_local_file = NULL;
+       if (p->info_or_local_file.s) {
+               mnd_efree(p->info_or_local_file.s);
+               p->info_or_local_file.s = NULL;
        }
        if (!stack_allocation) {
                mnd_pefree(p, p->header.persistent);
@@ -1961,10 +1961,10 @@ php_mysqlnd_stats_read(void * _packet)
                DBG_RETURN(FAIL);
        }
 
-       packet->message = mnd_emalloc(packet->header.size + 1);
-       memcpy(packet->message, buf, packet->header.size);
-       packet->message[packet->header.size] = '\0';
-       packet->message_len = packet->header.size;
+       packet->message.s = mnd_emalloc(packet->header.size + 1);
+       memcpy(packet->message.s, buf, packet->header.size);
+       packet->message.s[packet->header.size] = '\0';
+       packet->message.l = packet->header.size;
 
        DBG_RETURN(PASS);
 }
@@ -1976,9 +1976,9 @@ static
 void php_mysqlnd_stats_free_mem(void * _packet, zend_bool stack_allocation)
 {
        MYSQLND_PACKET_STATS *p= (MYSQLND_PACKET_STATS *) _packet;
-       if (p->message) {
-               mnd_efree(p->message);
-               p->message = NULL;
+       if (p->message.s) {
+               mnd_efree(p->message.s);
+               p->message.s = NULL;
        }
        if (!stack_allocation) {
                mnd_pefree(p, p->header.persistent);
@@ -2660,9 +2660,9 @@ mysqlnd_protocol_payload_decoder_factory_free(MYSQLND_PROTOCOL_PAYLOAD_DECODER_F
 
 
 
-/* {{{ send_command_do_request */
+/* {{{ send_command */
 static enum_func_status
-send_command_do_request(
+send_command(
                const enum php_mysqlnd_server_command command,
                const zend_uchar * const arg, const size_t arg_len,
                const zend_bool silent,
@@ -2678,7 +2678,7 @@ send_command_do_request(
 {
        enum_func_status ret = PASS;
        MYSQLND_PACKET_COMMAND * cmd_packet = NULL;
-       DBG_ENTER("send_command_do_request");
+       DBG_ENTER("send_command");
        DBG_INF_FMT("command=%s silent=%u", mysqlnd_command_to_text[command], silent);
        DBG_INF_FMT("server_status=%u", upsert_status->server_status);
        DBG_INF_FMT("sending %u bytes", arg_len + 1); /* + 1 is for the command */
@@ -2708,8 +2708,8 @@ send_command_do_request(
 
        cmd_packet->command = command;
        if (arg && arg_len) {
-               cmd_packet->argument = arg;
-               cmd_packet->arg_len  = arg_len;
+               cmd_packet->argument.s = arg;
+               cmd_packet->argument.l = arg_len;
        }
 
        MYSQLND_INC_CONN_STATISTIC(stats, STAT_COM_QUIT + command - 1 /* because of COM_SLEEP */ );
@@ -2730,6 +2730,113 @@ send_command_do_request(
 /* }}} */
 
 
+/* {{{ send_command_handle_response */
+enum_func_status
+send_command_handle_response(
+               const enum mysqlnd_packet_type ok_packet,
+               const zend_bool silent,
+               const enum php_mysqlnd_server_command command,
+               const zend_bool ignore_upsert_status,
+
+               MYSQLND_ERROR_INFO      * error_info,
+               MYSQLND_UPSERT_STATUS * upsert_status,
+               MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory,
+               MYSQLND_STRING * last_message,
+               zend_bool last_message_persistent
+       )
+{
+       enum_func_status ret = FAIL;
+
+       DBG_ENTER("send_command_handle_response");
+       DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
+
+       switch (ok_packet) {
+               case PROT_OK_PACKET:{
+                       MYSQLND_PACKET_OK * ok_response = payload_decoder_factory->m.get_ok_packet(payload_decoder_factory, FALSE);
+                       if (!ok_response) {
+                               SET_OOM_ERROR(error_info);
+                               break;
+                       }
+                       if (FAIL == (ret = PACKET_READ(ok_response))) {
+                               if (!silent) {
+                                       DBG_ERR_FMT("Error while reading %s's OK packet", mysqlnd_command_to_text[command]);
+                                       php_error_docref(NULL, E_WARNING, "Error while reading %s's OK packet. PID=%u",
+                                                                        mysqlnd_command_to_text[command], getpid());
+                               }
+                       } else {
+                               DBG_INF_FMT("OK from server");
+                               if (0xFF == ok_response->field_count) {
+                                       /* The server signalled error. Set the error */
+                                       SET_CLIENT_ERROR(error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+                                       ret = FAIL;
+                                       /*
+                                         Cover a protocol design error: error packet does not
+                                         contain the server status. Therefore, the client has no way
+                                         to find out whether there are more result sets of
+                                         a multiple-result-set statement pending. Luckily, in 5.0 an
+                                         error always aborts execution of a statement, wherever it is
+                                         a multi-statement or a stored procedure, so it should be
+                                         safe to unconditionally turn off the flag here.
+                                       */
+                                       upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+                                       UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
+                               } else {
+                                       SET_NEW_MESSAGE(last_message->s, last_message->l,
+                                                                       ok_response->message, ok_response->message_len,
+                                                                       last_message_persistent);
+
+                                       if (!ignore_upsert_status) {
+                                               UPSERT_STATUS_RESET(upsert_status);
+                                               upsert_status->warning_count = ok_response->warning_count;
+                                               upsert_status->server_status = ok_response->server_status;
+                                               upsert_status->affected_rows = ok_response->affected_rows;
+                                               upsert_status->last_insert_id = ok_response->last_insert_id;
+                                       }
+                               }
+                       }
+                       PACKET_FREE(ok_response);
+                       break;
+               }
+               case PROT_EOF_PACKET:{
+                       MYSQLND_PACKET_EOF * ok_response = payload_decoder_factory->m.get_eof_packet(payload_decoder_factory, FALSE);
+                       if (!ok_response) {
+                               SET_OOM_ERROR(error_info);
+                               break;
+                       }
+                       if (FAIL == (ret = PACKET_READ(ok_response))) {
+                               SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
+                                                                "Malformed packet");
+                               if (!silent) {
+                                       DBG_ERR_FMT("Error while reading %s's EOF packet", mysqlnd_command_to_text[command]);
+                                       php_error_docref(NULL, E_WARNING, "Error while reading %s's EOF packet. PID=%d",
+                                                                        mysqlnd_command_to_text[command], getpid());
+                               }
+                       } else if (0xFF == ok_response->field_count) {
+                               /* The server signalled error. Set the error */
+                               SET_CLIENT_ERROR(error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+                               UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
+                       } else if (0xFE != ok_response->field_count) {
+                               SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+                               if (!silent) {
+                                       DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count);
+                                       php_error_docref(NULL, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X",
+                                                                       ok_response->field_count);
+                               }
+                       } else {
+                               DBG_INF_FMT("OK from server");
+                       }
+                       PACKET_FREE(ok_response);
+                       break;
+               }
+               default:
+                       SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+                       php_error_docref(NULL, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
+                       break;
+       }
+       DBG_INF(ret == PASS ? "PASS":"FAIL");
+       DBG_RETURN(ret);
+}
+/* }}} */
 
 
 
@@ -2778,18 +2885,18 @@ mysqlnd_com_set_option_run(void *cmd)
        DBG_ENTER("mysqlnd_com_set_option_run");
        int2store(buffer, (unsigned int) option);
 
-       ret = send_command_do_request(COM_SET_OPTION, buffer, sizeof(buffer), FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_SET_OPTION, buffer, sizeof(buffer), FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret) {
-               ret = conn->m->send_command_handle_response(conn, PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE);
+               ret = send_command_handle_response(PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE,
+                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
-
        DBG_RETURN(ret);
 }
 /* }}} */
@@ -2826,16 +2933,17 @@ mysqlnd_com_debug_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_debug_run");
 
-       ret = send_command_do_request(COM_DEBUG, NULL, 0, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_DEBUG, NULL, 0, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret) {
-               ret = conn->m->send_command_handle_response(conn, PROT_EOF_PACKET, COM_DEBUG, COM_DEBUG, TRUE);
+               ret = send_command_handle_response(PROT_EOF_PACKET, COM_DEBUG, COM_DEBUG, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
 
        DBG_RETURN(ret);
@@ -2884,16 +2992,17 @@ mysqlnd_com_init_db_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_init_db_run");
 
-       ret = send_command_do_request(COM_INIT_DB, (zend_uchar*) command->context.db.s, command->context.db.l, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_INIT_DB, (zend_uchar*) command->context.db.s, command->context.db.l, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret) {
-               ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_INIT_DB, TRUE);
+               ret = send_command_handle_response(PROT_OK_PACKET, FALSE, COM_INIT_DB, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
 
        DBG_RETURN(ret);
@@ -2932,16 +3041,17 @@ mysqlnd_com_ping_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_ping_run");
 
-       ret = send_command_do_request(COM_PING, NULL, 0, TRUE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_PING, NULL, 0, TRUE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret) {
-               ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, TRUE, COM_PING, TRUE);
+               ret = send_command_handle_response(PROT_OK_PACKET, TRUE, COM_PING, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
 
        DBG_RETURN(ret);
@@ -3006,14 +3116,14 @@ mysqlnd_com_field_list_run(void *cmd)
                *p++ = '\0';
        }
 
-       ret = send_command_do_request(COM_FIELD_LIST, buff, p - buff, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_FIELD_LIST, buff, p - buff, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3052,14 +3162,14 @@ mysqlnd_com_statistics_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_statistics_run");
 
-       ret = send_command_do_request(COM_STATISTICS, NULL, 0, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STATISTICS, NULL, 0, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3109,16 +3219,17 @@ mysqlnd_com_process_kill_run(void *cmd)
        DBG_ENTER("mysqlnd_com_process_kill_run");
        int4store(buff, command->context.process_id);
 
-       ret = send_command_do_request(COM_PROCESS_KILL, buff, 4, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_PROCESS_KILL, buff, 4, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret && command->context.read_response) {
-               ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_PROCESS_KILL, TRUE);
+               ret = send_command_handle_response(PROT_OK_PACKET, FALSE, COM_PROCESS_KILL, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
 
        DBG_RETURN(ret);
@@ -3170,16 +3281,17 @@ mysqlnd_com_refresh_run(void *cmd)
        DBG_ENTER("mysqlnd_com_refresh_run");
        int1store(bits, command->context.options);
 
-       ret = send_command_do_request(COM_REFRESH, bits, 1, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_REFRESH, bits, 1, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret) {
-               ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_REFRESH, TRUE);
+               ret = send_command_handle_response(PROT_OK_PACKET, FALSE, COM_REFRESH, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
 
        DBG_RETURN(ret);
@@ -3231,16 +3343,17 @@ mysqlnd_com_shutdown_run(void *cmd)
        DBG_ENTER("mysqlnd_com_shutdown_run");
        int1store(bits, command->context.level);
 
-       ret = send_command_do_request(COM_SHUTDOWN, bits, 1, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_SHUTDOWN, bits, 1, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
        if (PASS == ret) {
-               ret = conn->m->send_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_SHUTDOWN, TRUE);
+               ret = send_command_handle_response(PROT_OK_PACKET, FALSE, COM_SHUTDOWN, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
        }
 
        DBG_RETURN(ret);
@@ -3289,14 +3402,14 @@ mysqlnd_com_quit_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_quit_run");
 
-       ret = send_command_do_request(COM_QUIT, NULL, 0, TRUE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_QUIT, NULL, 0, TRUE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3343,14 +3456,14 @@ mysqlnd_com_query_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_query_run");
 
-       ret = send_command_do_request(COM_QUERY, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_QUERY, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        if (PASS == ret) {
                SET_CONNECTION_STATE(&conn->state, CONN_QUERY_SENT);
@@ -3403,14 +3516,14 @@ mysqlnd_com_change_user_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_change_user_run");
 
-       ret = send_command_do_request(COM_CHANGE_USER, (zend_uchar*) command->context.payload.s, command->context.payload.l, command->context.silent,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_CHANGE_USER, (zend_uchar*) command->context.payload.s, command->context.payload.l, command->context.silent,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3512,14 +3625,14 @@ mysqlnd_com_stmt_prepare_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_stmt_prepare_run");
 
-       ret = send_command_do_request(COM_STMT_PREPARE, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STMT_PREPARE, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3568,14 +3681,14 @@ mysqlnd_com_stmt_execute_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_stmt_execute_run");
 
-       ret = send_command_do_request(COM_STMT_EXECUTE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STMT_EXECUTE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3624,14 +3737,14 @@ mysqlnd_com_stmt_fetch_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_stmt_fetch_run");
 
-       ret = send_command_do_request(COM_STMT_FETCH, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STMT_FETCH, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3682,14 +3795,18 @@ mysqlnd_com_stmt_reset_run(void *cmd)
        DBG_ENTER("mysqlnd_com_stmt_reset_run");
 
        int4store(cmd_buf, command->context.stmt_id);
-       ret = send_command_do_request(COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
+       if (PASS == ret) {
+               ret = send_command_handle_response(PROT_OK_PACKET, FALSE, COM_STMT_RESET, TRUE,
+                                                                                  conn->error_info, conn->upsert_status, conn->payload_decoder_factory, &conn->last_message, conn->persistent);
+       }
 
        DBG_RETURN(ret);
 }
@@ -3738,14 +3855,14 @@ mysqlnd_com_stmt_send_long_data_run(void *cmd)
 
        DBG_ENTER("mysqlnd_com_stmt_send_long_data_run");
 
-       ret = send_command_do_request(COM_STMT_SEND_LONG_DATA, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STMT_SEND_LONG_DATA, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
@@ -3796,14 +3913,14 @@ mysqlnd_com_stmt_close_run(void *cmd)
        DBG_ENTER("mysqlnd_com_stmt_close_run");
 
        int4store(cmd_buf, command->context.stmt_id);
-       ret = send_command_do_request(COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), FALSE,
-                                                                 &conn->state,
-                                                                 conn->error_info,
-                                                                 conn->upsert_status,
-                                                                 conn->stats,
-                                                                 conn->payload_decoder_factory,
-                                                                 conn->m->send_close,
-                                                                 conn);
+       ret = send_command(COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), FALSE,
+                                          &conn->state,
+                                          conn->error_info,
+                                          conn->upsert_status,
+                                          conn->stats,
+                                          conn->payload_decoder_factory,
+                                          conn->m->send_close,
+                                          conn);
 
        DBG_RETURN(ret);
 }
index 7dd318e20bd83575e879055781a8888bfdbcb765..8915cfd3947464f21e0654b6b11e56953e223c5f 100644 (file)
@@ -158,8 +158,7 @@ typedef struct st_mysqlnd_packet_ok {
 typedef struct st_mysqlnd_packet_command {
        MYSQLND_PACKET_HEADER                   header;
        enum php_mysqlnd_server_command command;
-       const zend_uchar                                *argument;
-       size_t                                                  arg_len;
+       MYSQLND_CSTRING argument;
 } MYSQLND_PACKET_COMMAND;
 
 
@@ -179,7 +178,7 @@ typedef struct st_mysqlnd_packet_eof {
 
 /* Result Set header*/
 typedef struct st_mysqlnd_packet_rset_header {
-       MYSQLND_PACKET_HEADER           header;
+       MYSQLND_PACKET_HEADER header;
        /*
          0x00 => ok
          ~0   => LOAD DATA LOCAL
@@ -196,8 +195,7 @@ typedef struct st_mysqlnd_packet_rset_header {
        uint64_t        affected_rows;
        uint64_t        last_insert_id;
        /* This is for both LOAD DATA or info, when no result set */
-       char            *info_or_local_file;
-       size_t          info_or_local_file_len;
+       MYSQLND_STRING info_or_local_file;
        /* If error packet, we use these */
        MYSQLND_ERROR_INFO      error_info;
 } MYSQLND_PACKET_RSET_HEADER;
@@ -248,9 +246,7 @@ typedef struct st_mysqlnd_packet_row {
 /* Statistics packet */
 typedef struct st_mysqlnd_packet_stats {
        MYSQLND_PACKET_HEADER   header;
-       char *message;
-       /* message_len is not part of the packet*/
-       size_t message_len;
+       MYSQLND_STRING message;
 } MYSQLND_PACKET_STATS;