php-src/ext/mysqlnd/mysqlnd_wireprotocol.h
Andrey Hristov 63791d055a New result fetching mode for mysqlnd, which should use less memory but
implies more memory copy. The old method is still available and can be used.
It stays as default. Choosing the method is through a flag to mysqli_query()/mysqli_real_query()
New mode can be forced with an INI setting, for all extensions that support this mode
(ext/mysql and mysqli, because PDO due to it's architecture can't support it)
The setting is mysqlnd.fetch_data_copy=[0|1]
2014-04-10 16:44:54 +03:00

337 lines
10 KiB
C

/*
+----------------------------------------------------------------------+
| PHP Version 5 |
+----------------------------------------------------------------------+
| Copyright (c) 2006-2014 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
| Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
/* $Id$ */
#ifndef MYSQLND_WIREPROTOCOL_H
#define MYSQLND_WIREPROTOCOL_H
#include "mysqlnd_net.h"
#define MYSQLND_HEADER_SIZE 4
#define COMPRESSED_HEADER_SIZE 3
#define MYSQLND_NULL_LENGTH (unsigned long) ~0
/* Used in mysqlnd_debug.c */
PHPAPI extern const char mysqlnd_read_header_name[];
PHPAPI extern const char mysqlnd_read_body_name[];
/* Packet handling */
#define PACKET_WRITE(packet, conn) ((packet)->header.m->write_to_net((packet), (conn) TSRMLS_CC))
#define PACKET_READ(packet, conn) ((packet)->header.m->read_from_net((packet), (conn) TSRMLS_CC))
#define PACKET_FREE(packet) \
do { \
DBG_INF_FMT("PACKET_FREE(%p)", packet); \
if ((packet)) { \
((packet)->header.m->free_mem((packet), FALSE TSRMLS_CC)); \
} \
} while (0);
PHPAPI extern const char * const mysqlnd_command_to_text[COM_END];
/* Low-level extraction functionality */
typedef struct st_mysqlnd_packet_methods {
size_t struct_size;
enum_func_status (*read_from_net)(void * packet, MYSQLND_CONN_DATA * conn TSRMLS_DC);
size_t (*write_to_net)(void * packet, MYSQLND_CONN_DATA * conn TSRMLS_DC);
void (*free_mem)(void *packet, zend_bool stack_allocation TSRMLS_DC);
} mysqlnd_packet_methods;
typedef struct st_mysqlnd_packet_header {
size_t size;
mysqlnd_packet_methods *m;
zend_uchar packet_no;
zend_bool persistent;
} MYSQLND_PACKET_HEADER;
/* Server greets the client */
typedef struct st_mysqlnd_packet_greet {
MYSQLND_PACKET_HEADER header;
uint8_t protocol_version;
char *server_version;
uint32_t thread_id;
zend_uchar intern_auth_plugin_data[SCRAMBLE_LENGTH];
zend_uchar * auth_plugin_data;
size_t auth_plugin_data_len;
/* 1 byte pad */
uint32_t server_capabilities;
uint8_t charset_no;
uint16_t server_status;
/* 13 byte pad, in 5.5 first 2 bytes are more capabilities followed by 1 byte scramble_length */
zend_bool pre41;
/* If error packet, we use these */
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
char *auth_protocol;
} MYSQLND_PACKET_GREET;
/* Client authenticates */
typedef struct st_mysqlnd_packet_auth {
MYSQLND_PACKET_HEADER header;
uint32_t client_flags;
uint32_t max_packet_size;
uint8_t charset_no;
const char *user;
const zend_uchar *auth_data;
size_t auth_data_len;
const char *db;
const char *auth_plugin_name;
/* Here the packet ends. This is user supplied data */
size_t db_len;
zend_bool send_auth_data;
zend_bool is_change_user_packet;
zend_bool silent;
HashTable *connect_attr;
} MYSQLND_PACKET_AUTH;
/* Auth response packet */
typedef struct st_mysqlnd_packet_auth_response {
MYSQLND_PACKET_HEADER header;
uint8_t response_code;
uint64_t affected_rows;
uint64_t last_insert_id;
uint16_t server_status;
uint16_t warning_count;
char *message;
size_t message_len;
/* If error packet, we use these */
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
char *new_auth_protocol;
size_t new_auth_protocol_len;
zend_uchar *new_auth_protocol_data;
size_t new_auth_protocol_data_len;
} MYSQLND_PACKET_AUTH_RESPONSE;
/* Auth response packet */
typedef struct st_mysqlnd_packet_change_auth_response {
MYSQLND_PACKET_HEADER header;
const zend_uchar *auth_data;
size_t auth_data_len;
} MYSQLND_PACKET_CHANGE_AUTH_RESPONSE;
/* OK packet */
typedef struct st_mysqlnd_packet_ok {
MYSQLND_PACKET_HEADER header;
uint8_t field_count; /* always 0x0 */
uint64_t affected_rows;
uint64_t last_insert_id;
uint16_t server_status;
uint16_t warning_count;
char *message;
size_t message_len;
/* If error packet, we use these */
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
} MYSQLND_PACKET_OK;
/* Command packet */
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_PACKET_COMMAND;
/* EOF packet */
typedef struct st_mysqlnd_packet_eof {
MYSQLND_PACKET_HEADER header;
uint8_t field_count; /* 0xFE */
uint16_t warning_count;
uint16_t server_status;
/* If error packet, we use these */
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
} MYSQLND_PACKET_EOF;
/* EOF packet */
/* Result Set header*/
typedef struct st_mysqlnd_packet_rset_header {
MYSQLND_PACKET_HEADER header;
/*
0x00 => ok
~0 => LOAD DATA LOCAL
error_no != 0 => error
others => result set -> Read res_field packets up to field_count
*/
unsigned long field_count;
/*
These are filled if no SELECT query. For SELECT warning_count
and server status are in the last row packet, the EOF packet.
*/
uint16_t warning_count;
uint16_t server_status;
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;
/* If error packet, we use these */
MYSQLND_ERROR_INFO error_info;
} MYSQLND_PACKET_RSET_HEADER;
/* Result set field packet */
typedef struct st_mysqlnd_packet_res_field {
MYSQLND_PACKET_HEADER header;
MYSQLND_FIELD *metadata;
/* For table definitions, empty for result sets */
zend_bool skip_parsing;
zend_bool stupid_list_fields_eof;
zend_bool persistent_alloc;
MYSQLND_ERROR_INFO error_info;
} MYSQLND_PACKET_RES_FIELD;
/* Row packet */
typedef struct st_mysqlnd_packet_row {
MYSQLND_PACKET_HEADER header;
zval **fields;
uint32_t field_count;
zend_bool eof;
/*
These are, of course, only for SELECT in the EOF packet,
which is detected by this packet
*/
uint16_t warning_count;
uint16_t server_status;
struct st_mysqlnd_memory_pool_chunk *row_buffer;
MYSQLND_MEMORY_POOL * result_set_memory_pool;
zend_bool skip_extraction;
zend_bool binary_protocol;
zend_bool persistent_alloc;
MYSQLND_FIELD *fields_metadata;
/* We need this to alloc bigger bufs in non-PS mode */
unsigned int bit_fields_count;
size_t bit_fields_total_len; /* trailing \0 not counted */
/* If error packet, we use these */
MYSQLND_ERROR_INFO error_info;
} 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_PACKET_STATS;
/* COM_PREPARE response packet */
typedef struct st_mysqlnd_packet_prepare_response {
MYSQLND_PACKET_HEADER header;
/* also known as field_count 0x00=OK , 0xFF=error */
unsigned char error_code;
unsigned long stmt_id;
unsigned int field_count;
unsigned int param_count;
unsigned int warning_count;
/* present in case of error */
MYSQLND_ERROR_INFO error_info;
} MYSQLND_PACKET_PREPARE_RESPONSE;
/* Statistics packet */
typedef struct st_mysqlnd_packet_chg_user_resp {
MYSQLND_PACKET_HEADER header;
uint32_t response_code;
/* message_len is not part of the packet*/
uint16_t server_capabilities;
/* If error packet, we use these */
MYSQLND_ERROR_INFO error_info;
zend_bool server_asked_323_auth;
char *new_auth_protocol;
size_t new_auth_protocol_len;
zend_uchar *new_auth_protocol_data;
size_t new_auth_protocol_data_len;
} MYSQLND_PACKET_CHG_USER_RESPONSE;
/* Command packet */
typedef struct st_mysqlnd_packet_sha256_pk_request {
MYSQLND_PACKET_HEADER header;
} MYSQLND_PACKET_SHA256_PK_REQUEST;
typedef struct st_mysqlnd_packet_sha256_pk_request_response {
MYSQLND_PACKET_HEADER header;
zend_uchar *public_key;
size_t public_key_len;
} MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE;
PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len);
unsigned long php_mysqlnd_net_field_length(zend_uchar **packet);
zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);
size_t php_mysqlnd_net_store_length_size(uint64_t length);
PHPAPI const extern char * const mysqlnd_empty_string;
enum_func_status php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status php_mysqlnd_rowp_read_text_protocol_zval(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
enum_func_status php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval ** fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats TSRMLS_DC);
PHPAPI MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent TSRMLS_DC);
PHPAPI void mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol TSRMLS_DC);
#endif /* MYSQLND_WIREPROTOCOL_H */
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
* vim600: noet sw=4 ts=4 fdm=marker
* vim<600: noet sw=4 ts=4
*/