Browse Source

Update ext/mysql, ext/mysqli and ext/mysqlnd from development tree

experimental/first_unicode_implementation
Andrey Hristov 19 years ago
parent
commit
c931468b88
  1. 6
      ext/mysql/php_mysql.c
  2. 14
      ext/mysqli/mysqli_api.c
  3. 15
      ext/mysqlnd/mysqlnd.c
  4. 10
      ext/mysqlnd/mysqlnd.h
  5. 2
      ext/mysqlnd/mysqlnd_debug.h
  6. 3
      ext/mysqlnd/mysqlnd_libmysql_compat.h
  7. 4
      ext/mysqlnd/mysqlnd_loaddata.c
  8. 260
      ext/mysqlnd/mysqlnd_ps.c
  9. 114
      ext/mysqlnd/mysqlnd_ps_codec.c
  10. 38
      ext/mysqlnd/mysqlnd_result.c
  11. 18
      ext/mysqlnd/mysqlnd_result_meta.c
  12. 80
      ext/mysqlnd/mysqlnd_structs.h
  13. 10
      ext/mysqlnd/mysqlnd_wireprotocol.c
  14. 2
      ext/mysqlnd/php_mysqlnd.c

6
ext/mysql/php_mysql.c

@ -1882,7 +1882,7 @@ PHP_FUNCTION(mysql_result)
switch(Z_TYPE_PP(field)) { switch(Z_TYPE_PP(field)) {
case IS_STRING: { case IS_STRING: {
int i=0; int i=0;
MYSQL_FIELD *tmp_field;
const MYSQL_FIELD *tmp_field;
char *table_name, *field_name, *tmp; char *table_name, *field_name, *tmp;
if ((tmp=strchr(Z_STRVAL_PP(field), '.'))) { if ((tmp=strchr(Z_STRVAL_PP(field), '.'))) {
@ -2412,7 +2412,7 @@ PHP_FUNCTION(mysql_fetch_field)
{ {
zval **result, **field=NULL; zval **result, **field=NULL;
MYSQL_RES *mysql_result; MYSQL_RES *mysql_result;
MYSQL_FIELD *mysql_field;
const MYSQL_FIELD *mysql_field;
switch (ZEND_NUM_ARGS()) { switch (ZEND_NUM_ARGS()) {
case 1: case 1:
@ -2497,7 +2497,7 @@ static void php_mysql_field_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
{ {
zval **result, **field; zval **result, **field;
MYSQL_RES *mysql_result; MYSQL_RES *mysql_result;
MYSQL_FIELD *mysql_field = {0};
const MYSQL_FIELD *mysql_field = {0};
char buf[512]; char buf[512];
int len; int len;

14
ext/mysqli/mysqli_api.c

@ -166,7 +166,7 @@ int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned in
if (argc == start) { if (argc == start) {
return PASS; return PASS;
} }
params = emalloc((argc - start) * sizeof(MYSQLND_PARAM_BIND));
params = safe_emalloc(argc - start, sizeof(MYSQLND_PARAM_BIND), 0);
for (i = 0; i < (argc - start); i++) { for (i = 0; i < (argc - start); i++) {
zend_uchar type; zend_uchar type;
switch (types[i]) { switch (types[i]) {
@ -445,7 +445,7 @@ mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc,
unsigned int i; unsigned int i;
MYSQLND_RESULT_BIND *params; MYSQLND_RESULT_BIND *params;
params = emalloc((argc - start) * sizeof(MYSQLND_RESULT_BIND));
params = safe_emalloc(argc - start, sizeof(MYSQLND_RESULT_BIND), 0);
for (i = 0; i < (argc - start); i++) { for (i = 0; i < (argc - start); i++) {
params[i].zv = *(args[i + start]); params[i].zv = *(args[i + start]);
} }
@ -1038,7 +1038,7 @@ PHP_FUNCTION(mysqli_stmt_fetch)
/* }}} */ /* }}} */
/* {{{ php_add_field_properties */ /* {{{ php_add_field_properties */
static void php_add_field_properties(zval *value, MYSQL_FIELD *field TSRMLS_DC)
static void php_add_field_properties(zval *value, const MYSQL_FIELD *field TSRMLS_DC)
{ {
add_property_utf8_string(value, "name",(field->name ? field->name : ""), ZSTR_DUPLICATE); add_property_utf8_string(value, "name",(field->name ? field->name : ""), ZSTR_DUPLICATE);
add_property_utf8_string(value, "orgname",(field->org_name ? field->org_name : ""), ZSTR_DUPLICATE); add_property_utf8_string(value, "orgname",(field->org_name ? field->org_name : ""), ZSTR_DUPLICATE);
@ -1061,7 +1061,7 @@ PHP_FUNCTION(mysqli_fetch_field)
{ {
MYSQL_RES *result; MYSQL_RES *result;
zval *mysql_result; zval *mysql_result;
MYSQL_FIELD *field;
const MYSQL_FIELD *field;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
return; return;
@ -1084,9 +1084,7 @@ PHP_FUNCTION(mysqli_fetch_fields)
{ {
MYSQL_RES *result; MYSQL_RES *result;
zval *mysql_result; zval *mysql_result;
MYSQL_FIELD *field;
zval *obj; zval *obj;
unsigned int i; unsigned int i;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
@ -1098,7 +1096,7 @@ PHP_FUNCTION(mysqli_fetch_fields)
array_init(return_value); array_init(return_value);
for (i = 0; i < mysql_num_fields(result); i++) { for (i = 0; i < mysql_num_fields(result); i++) {
field = mysql_fetch_field_direct(result, i);
const MYSQL_FIELD *field = mysql_fetch_field_direct(result, i);
MAKE_STD_ZVAL(obj); MAKE_STD_ZVAL(obj);
object_init(obj); object_init(obj);
@ -1115,7 +1113,7 @@ PHP_FUNCTION(mysqli_fetch_field_direct)
{ {
MYSQL_RES *result; MYSQL_RES *result;
zval *mysql_result; zval *mysql_result;
MYSQL_FIELD *field;
const MYSQL_FIELD *field;
long offset; long offset;
if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) { if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) {

15
ext/mysqlnd/mysqlnd.c

@ -171,7 +171,7 @@ MYSQLND_METHOD(mysqlnd_conn, free_contents)(MYSQLND *conn TSRMLS_DC)
} }
if (conn->options.num_commands) { if (conn->options.num_commands) {
unsigned int i; unsigned int i;
for (i=0; i < conn->options.num_commands; i++) {
for (i = 0; i < conn->options.num_commands; i++) {
mnd_pefree(conn->options.init_commands[i], pers); mnd_pefree(conn->options.init_commands[i], pers);
} }
mnd_pefree(conn->options.init_commands, pers); mnd_pefree(conn->options.init_commands, pers);
@ -477,7 +477,7 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
{ {
char *transport = NULL, *errstr = NULL; char *transport = NULL, *errstr = NULL;
char *hashed_details = NULL; char *hashed_details = NULL;
int transport_len, hashed_details_len, errcode = 0;
int transport_len, hashed_details_len, errcode = 0, host_len;
unsigned int streams_options = ENFORCE_SAFE_MODE; unsigned int streams_options = ENFORCE_SAFE_MODE;
unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT;
zend_bool self_alloced = FALSE; zend_bool self_alloced = FALSE;
@ -530,8 +530,9 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
if (!port && !socket) { if (!port && !socket) {
port = 3306; port = 3306;
} }
host_len = strlen(host);
#ifndef PHP_WIN32 #ifndef PHP_WIN32
if (!strncasecmp(host, "localhost", sizeof("localhost") - 1)) {
if (host_len == sizeof("localhost") - 1 && !strncasecmp(host, "localhost", host_len)) {
if (!socket) { if (!socket) {
socket = "/tmp/mysql.sock"; socket = "/tmp/mysql.sock";
} }
@ -555,14 +556,6 @@ PHPAPI MYSQLND *mysqlnd_connect(MYSQLND *conn,
} }
if (conn->persistent) { if (conn->persistent) {
#if 0
struct timeval tv;
gettimeofday(&tv, NULL);
/* We should generate something unique */
hashed_details_len = spprintf(&hashed_details, 0, "%s@%s@%s@%ld@%ld@%0.8F",
transport, user, db, tv.tv_sec, (long int)tv.tv_usec,
php_combined_lcg(TSRMLS_C) * 10);
#endif
hashed_details_len = spprintf(&hashed_details, 0, "%p", conn); hashed_details_len = spprintf(&hashed_details, 0, "%p", conn);
DBG_INF_FMT("hashed_details=%s", hashed_details); DBG_INF_FMT("hashed_details=%s", hashed_details);
} }

10
ext/mysqlnd/mysqlnd.h

@ -147,6 +147,7 @@ void _mysqlnd_debug(const char *mode TSRMLS_DC);
#define mysqlnd_field_tell(result) (result)->meta? (result)->meta->current_field:0) #define mysqlnd_field_tell(result) (result)->meta? (result)->meta->current_field:0)
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC) #define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC)
#define mysqlnd_fetch_field_direct(result,fnr) ((result)->meta? &((result)->meta->fields[(fnr)]):NULL) #define mysqlnd_fetch_field_direct(result,fnr) ((result)->meta? &((result)->meta->fields[(fnr)]):NULL)
#define mysqlnd_fetch_fields(result) ((result)->meta? (result)->meta->fields: NULL)
/* mysqlnd metadata */ /* mysqlnd metadata */
#define mysqlnd_get_client_info() MYSQLND_VERSION #define mysqlnd_get_client_info() MYSQLND_VERSION
@ -197,6 +198,7 @@ PHPAPI unsigned long * mysqlnd_fetch_lengths(MYSQLND_RES * const result);
#define mysqlnd_field_tell(result) (result)->m.field_tell((result)) #define mysqlnd_field_tell(result) (result)->m.field_tell((result))
#define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC) #define mysqlnd_fetch_field(result) (result)->m.fetch_field((result) TSRMLS_CC)
#define mysqlnd_fetch_field_direct(result,fnr) (result)->m.fetch_field_direct((result), (fnr) TSRMLS_CC) #define mysqlnd_fetch_field_direct(result,fnr) (result)->m.fetch_field_direct((result), (fnr) TSRMLS_CC)
#define mysqlnd_fetch_fields(result) (result)->m.fetch_fields((result) TSRMLS_CC)
/* mysqlnd metadata */ /* mysqlnd metadata */
PHPAPI const char * mysqlnd_get_client_info(); PHPAPI const char * mysqlnd_get_client_info();
@ -216,6 +218,9 @@ PHPAPI unsigned int mysqlnd_get_client_version();
/*****************************************************************************************************/ /*****************************************************************************************************/
PHPAPI void mysqlnd_efree_param_bind_dtor(MYSQLND_PARAM_BIND * param_bind);
PHPAPI void mysqlnd_efree_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind);
PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type); PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
@ -261,9 +266,12 @@ PHPAPI ulong mysqlnd_old_escape_string(char *newstr, const char *escapestr, size
#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen) TSRMLS_CC) #define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen) TSRMLS_CC)
#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt) TSRMLS_CC) #define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt) TSRMLS_CC)
#define mysqlnd_stmt_send_long_data(s,p,d,l) (s)->m->send_long_data((s), (p), (d), (l) TSRMLS_CC) #define mysqlnd_stmt_send_long_data(s,p,d,l) (s)->m->send_long_data((s), (p), (d), (l) TSRMLS_CC)
#define mysqlnd_stmt_bind_param(stmt,bind) (stmt)->m->bind_param((stmt), (bind) TSRMLS_CC)
#define mysqlnd_stmt_bind_param(stmt,bind) (stmt)->m->bind_parameters((stmt), (bind) TSRMLS_CC)
#define mysqlnd_stmt_bind_one_param(s,n,z,t) (s)->m->bind_one_parameter((s), (n), (z), (t) TSRMLS_CC)
#define mysqlnd_stmt_refresh_bind_param(s) (s)->m->refresh_bind_param((s) TSRMLS_CC) #define mysqlnd_stmt_refresh_bind_param(s) (s)->m->refresh_bind_param((s) TSRMLS_CC)
#define mysqlnd_stmt_set_param_bind_dtor(s,d) (s)->m->set_param_bind_dtor((s), (d) TSRMLS_CC)
#define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind) TSRMLS_CC) #define mysqlnd_stmt_bind_result(stmt,bind) (stmt)->m->bind_result((stmt), (bind) TSRMLS_CC)
#define mysqlnd_stmt_set_result_bind_dtor(s,d) (s)->m->set_result_bind_dtor((s), (d) TSRMLS_CC)
#define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt)) #define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt))
#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt) TSRMLS_CC) #define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt) TSRMLS_CC)

2
ext/mysqlnd/mysqlnd_debug.h

@ -89,8 +89,6 @@ char * mysqlnd_get_backtrace(TSRMLS_D);
#define DBG_RETURN(value) do { if (MYSQLND_G(dbg)) MYSQLND_G(dbg)->m->func_leave(MYSQLND_G(dbg), __LINE__, __FILE__); return (value); } while (0) #define DBG_RETURN(value) do { if (MYSQLND_G(dbg)) MYSQLND_G(dbg)->m->func_leave(MYSQLND_G(dbg), __LINE__, __FILE__); return (value); } while (0)
#define DBG_VOID_RETURN do { if (MYSQLND_G(dbg)) MYSQLND_G(dbg)->m->func_leave(MYSQLND_G(dbg), __LINE__, __FILE__); return; } while (0) #define DBG_VOID_RETURN do { if (MYSQLND_G(dbg)) MYSQLND_G(dbg)->m->func_leave(MYSQLND_G(dbg), __LINE__, __FILE__); return; } while (0)
#elif MYSQLND_DBG_ENABLED == 0 #elif MYSQLND_DBG_ENABLED == 0

3
ext/mysqlnd/mysqlnd_libmysql_compat.h

@ -57,6 +57,7 @@
#define mysql_escape_string(a,b,c) mysqlnd_escape_string((a), (b), (c)) #define mysql_escape_string(a,b,c) mysqlnd_escape_string((a), (b), (c))
#define mysql_fetch_field(r) mysqlnd_fetch_field((r)) #define mysql_fetch_field(r) mysqlnd_fetch_field((r))
#define mysql_fetch_field_direct(r,o) mysqlnd_fetch_field_direct((r), (o)) #define mysql_fetch_field_direct(r,o) mysqlnd_fetch_field_direct((r), (o))
#define mysql_fetch_fields(r) mysqlnd_fetch_fields((r))
#define mysql_fetch_lengths(r) mysqlnd_fetch_lengths((r)) #define mysql_fetch_lengths(r) mysqlnd_fetch_lengths((r))
#define mysql_fetch_row(r) mysqlnd_fetch_row_c((r)) #define mysql_fetch_row(r) mysqlnd_fetch_row_c((r))
#define mysql_field_count(r) mysqlnd_field_count((r)) #define mysql_field_count(r) mysqlnd_field_count((r))
@ -87,6 +88,8 @@
#define mysql_stmt_num_rows(s) mysqlnd_stmt_num_rows((s)) #define mysql_stmt_num_rows(s) mysqlnd_stmt_num_rows((s))
#define mysql_stmt_insert_id(s) mysqlnd_stmt_insert_id((s)) #define mysql_stmt_insert_id(s) mysqlnd_stmt_insert_id((s))
#define mysql_stmt_close(s) mysqlnd_stmt_close((s)) #define mysql_stmt_close(s) mysqlnd_stmt_close((s))
#define mysql_stmt_bind_param(s,b) mysqlnd_stmt_bind_param((s), (b))
#define mysql_stmt_bind_result(s,b) mysqlnd_stmt_bind_result((s), (b))
#define mysql_stmt_errno(s) mysqlnd_stmt_errno((s)) #define mysql_stmt_errno(s) mysqlnd_stmt_errno((s))
#define mysql_stmt_error(s) mysqlnd_stmt_error((s)) #define mysql_stmt_error(s) mysqlnd_stmt_error((s))
#define mysql_stmt_sqlstate(s) mysqlnd_stmt_sqlstate((s)) #define mysql_stmt_sqlstate(s) mysqlnd_stmt_sqlstate((s))

4
ext/mysqlnd/mysqlnd_loaddata.c

@ -58,7 +58,7 @@ int mysqlnd_local_infile_init(void **ptr, char *filename, void **userdata TSRMLS
DBG_ENTER("mysqlnd_local_infile_init"); DBG_ENTER("mysqlnd_local_infile_init");
*ptr= info= ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
*ptr = info = ((MYSQLND_INFILE_INFO *)mnd_ecalloc(1, sizeof(MYSQLND_INFILE_INFO)));
/* check open_basedir */ /* check open_basedir */
if (PG(open_basedir)) { if (PG(open_basedir)) {
@ -88,7 +88,7 @@ static
int mysqlnd_local_infile_read(void *ptr, char *buf, uint buf_len TSRMLS_DC) int mysqlnd_local_infile_read(void *ptr, char *buf, uint buf_len TSRMLS_DC)
{ {
MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr; MYSQLND_INFILE_INFO *info = (MYSQLND_INFILE_INFO *)ptr;
int count;
int count;
DBG_ENTER("mysqlnd_local_infile_read"); DBG_ENTER("mysqlnd_local_infile_read");

260
ext/mysqlnd/mysqlnd_ps.c

@ -56,7 +56,7 @@ enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param,
unsigned int flags, unsigned int flags,
zend_bool *fetched_anything TSRMLS_DC); zend_bool *fetched_anything TSRMLS_DC);
void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
/* {{{ mysqlnd_stmt::store_result */ /* {{{ mysqlnd_stmt::store_result */
@ -78,8 +78,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
if (stmt->cursor_exists) { if (stmt->cursor_exists) {
/* Silently convert buffered to unbuffered, for now */ /* Silently convert buffered to unbuffered, for now */
MYSQLND_RES * res = stmt->m->use_result(stmt TSRMLS_CC);
DBG_RETURN(res);
DBG_RETURN(stmt->m->use_result(stmt TSRMLS_CC));
} }
/* Nothing to store for UPSERT/LOAD DATA*/ /* Nothing to store for UPSERT/LOAD DATA*/
@ -135,7 +134,7 @@ MYSQLND_METHOD(mysqlnd_stmt, background_store_result)(MYSQLND_STMT * const stmt
MYSQLND_RES *result; MYSQLND_RES *result;
zend_bool to_cache = FALSE; zend_bool to_cache = FALSE;
DBG_ENTER("mysqlnd_stmt::store_result");
DBG_ENTER("mysqlnd_stmt::background_store_result");
DBG_INF_FMT("stmt=%lu", stmt->stmt_id); DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
/* be compliant with libmysql - NULL will turn */ /* be compliant with libmysql - NULL will turn */
@ -198,6 +197,7 @@ MYSQLND_METHOD(mysqlnd_stmt, background_store_result)(MYSQLND_STMT * const stmt
} }
/* }}} */ /* }}} */
/* {{{ mysqlnd_stmt::get_result */ /* {{{ mysqlnd_stmt::get_result */
static MYSQLND_RES * static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC) MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
@ -215,8 +215,7 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const stmt TSRMLS_DC)
if (stmt->cursor_exists) { if (stmt->cursor_exists) {
/* Silently convert buffered to unbuffered, for now */ /* Silently convert buffered to unbuffered, for now */
MYSQLND_RES * res = stmt->m->use_result(stmt TSRMLS_CC);
DBG_RETURN(res);
DBG_RETURN(stmt->m->use_result(stmt TSRMLS_CC));
} }
/* Nothing to store for UPSERT/LOAD DATA*/ /* Nothing to store for UPSERT/LOAD DATA*/
@ -255,6 +254,7 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT *stmt TSRMLS_DC)
{ {
/* Follows parameter metadata, we have just to skip it, as libmysql does */ /* Follows parameter metadata, we have just to skip it, as libmysql does */
unsigned int i = 0; unsigned int i = 0;
enum_func_status ret = PASS;
php_mysql_packet_res_field field_packet; php_mysql_packet_res_field field_packet;
DBG_ENTER("mysqlnd_stmt_skip_metadata"); DBG_ENTER("mysqlnd_stmt_skip_metadata");
@ -264,13 +264,13 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT *stmt TSRMLS_DC)
field_packet.skip_parsing = TRUE; field_packet.skip_parsing = TRUE;
for (;i < stmt->param_count; i++) { for (;i < stmt->param_count; i++) {
if (FAIL == PACKET_READ_ALLOCA(field_packet, stmt->conn)) { if (FAIL == PACKET_READ_ALLOCA(field_packet, stmt->conn)) {
PACKET_FREE_ALLOCA(field_packet);
DBG_RETURN(FAIL);
ret = FAIL;
break;
} }
} }
PACKET_FREE_ALLOCA(field_packet); PACKET_FREE_ALLOCA(field_packet);
DBG_RETURN(PASS);
DBG_RETURN(ret);
} }
/* }}} */ /* }}} */
@ -280,19 +280,21 @@ static enum_func_status
mysqlnd_stmt_read_prepare_response(MYSQLND_STMT *stmt TSRMLS_DC) mysqlnd_stmt_read_prepare_response(MYSQLND_STMT *stmt TSRMLS_DC)
{ {
php_mysql_packet_prepare_response prepare_resp; php_mysql_packet_prepare_response prepare_resp;
enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_stmt_read_prepare_response"); DBG_ENTER("mysqlnd_stmt_read_prepare_response");
DBG_INF_FMT("stmt=%lu", stmt->stmt_id); DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
PACKET_INIT_ALLOCA(prepare_resp, PROT_PREPARE_RESP_PACKET); PACKET_INIT_ALLOCA(prepare_resp, PROT_PREPARE_RESP_PACKET);
if (FAIL == PACKET_READ_ALLOCA(prepare_resp, stmt->conn)) { if (FAIL == PACKET_READ_ALLOCA(prepare_resp, stmt->conn)) {
PACKET_FREE_ALLOCA(prepare_resp);
return FAIL;
ret = FAIL;
goto done;
} }
if (0xFF == prepare_resp.error_code) { if (0xFF == prepare_resp.error_code) {
stmt->error_info = stmt->conn->error_info = prepare_resp.error_info; stmt->error_info = stmt->conn->error_info = prepare_resp.error_info;
return FAIL;
ret = FAIL;
goto done;
} }
stmt->stmt_id = prepare_resp.stmt_id; stmt->stmt_id = prepare_resp.stmt_id;
@ -301,7 +303,8 @@ mysqlnd_stmt_read_prepare_response(MYSQLND_STMT *stmt TSRMLS_DC)
stmt->param_count = prepare_resp.param_count; stmt->param_count = prepare_resp.param_count;
PACKET_FREE_ALLOCA(prepare_resp); PACKET_FREE_ALLOCA(prepare_resp);
DBG_RETURN(PASS);
done:
DBG_RETURN(ret);
} }
/* }}} */ /* }}} */
@ -487,13 +490,31 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
DBG_RETURN(FAIL); DBG_RETURN(FAIL);
} }
if (stmt->param_count && !stmt->param_bind) {
SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE,
"No data supplied for parameters in prepared statement");
DBG_INF("FAIL");
DBG_RETURN(FAIL);
if (stmt->param_count) {
uint i, not_bound = 0;
if (!stmt->param_bind) {
SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE,
"No data supplied for parameters in prepared statement");
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
for (i = 0; i < stmt->param_count; i++) {
if (stmt->param_bind[i].zv == NULL) {
not_bound++;
}
}
if (not_bound) {
char * msg;
spprintf(&msg, 0, "No data supplied for %d parameter%s in prepared statement",
not_bound, not_bound>1 ?"s":"");
SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg);
if (msg) {
efree(msg);
}
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
} }
request = mysqlnd_stmt_execute_generate_request(stmt, &request_len, &free_request TSRMLS_CC); request = mysqlnd_stmt_execute_generate_request(stmt, &request_len, &free_request TSRMLS_CC);
/* support for buffer types should be added here ! */ /* support for buffer types should be added here ! */
@ -553,7 +574,7 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const stmt TSRMLS_DC)
use_result() or store_result() and we should be able to scrap the use_result() or store_result() and we should be able to scrap the
data on the line, if he just decides to close the statement. data on the line, if he just decides to close the statement.
*/ */
DBG_INF_FMT("server_status=%d cursor=%d\n", stmt->upsert_status.server_status,
DBG_INF_FMT("server_status=%d cursor=%d", stmt->upsert_status.server_status,
stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS); stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS);
if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) { if (stmt->upsert_status.server_status & SERVER_STATUS_CURSOR_EXISTS) {
@ -595,10 +616,9 @@ enum_func_status
mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags, mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
zend_bool *fetched_anything TSRMLS_DC) zend_bool *fetched_anything TSRMLS_DC)
{ {
unsigned int i;
MYSQLND_STMT *stmt = (MYSQLND_STMT *) param; MYSQLND_STMT *stmt = (MYSQLND_STMT *) param;
uint field_count = result->meta->field_count;
MYSQLND_RES_BUFFERED *set = result->stored_data; MYSQLND_RES_BUFFERED *set = result->stored_data;
uint field_count = result->meta->field_count;
DBG_ENTER("mysqlnd_fetch_stmt_row_buffered"); DBG_ENTER("mysqlnd_fetch_stmt_row_buffered");
DBG_INF_FMT("stmt=%lu", stmt->stmt_id); DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
@ -609,6 +629,8 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
{ {
/* The user could have skipped binding - don't crash*/ /* The user could have skipped binding - don't crash*/
if (stmt->result_bind) { if (stmt->result_bind) {
unsigned int i;
MYSQLND_RES_METADATA * meta = result->meta;
zval **current_row = set->data_cursor; zval **current_row = set->data_cursor;
if (NULL == current_row[0]) { if (NULL == current_row[0]) {
@ -616,8 +638,8 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
set->initialized_rows++; set->initialized_rows++;
result->m.row_decoder(set->row_buffers[row_num], result->m.row_decoder(set->row_buffers[row_num],
current_row, current_row,
result->meta->field_count,
result->meta->fields,
meta->field_count,
meta->fields,
result->conn TSRMLS_CC); result->conn TSRMLS_CC);
if (stmt->update_max_length) { if (stmt->update_max_length) {
for (i = 0; i < result->field_count; i++) { for (i = 0; i < result->field_count; i++) {
@ -628,8 +650,8 @@ mysqlnd_fetch_stmt_row_buffered(MYSQLND_RES *result, void *param, unsigned int f
*/ */
if (Z_TYPE_P(current_row[i]) >= IS_STRING) { if (Z_TYPE_P(current_row[i]) >= IS_STRING) {
unsigned long len = Z_STRLEN_P(current_row[i]); unsigned long len = Z_STRLEN_P(current_row[i]);
if (result->meta->fields[i].max_length < len) {
result->meta->fields[i].max_length = len;
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
} }
} }
} }
@ -687,7 +709,6 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
{ {
enum_func_status ret; enum_func_status ret;
MYSQLND_STMT *stmt = (MYSQLND_STMT *) param; MYSQLND_STMT *stmt = (MYSQLND_STMT *) param;
unsigned int i, field_count = result->field_count;
php_mysql_packet_row *row_packet = result->row_packet; php_mysql_packet_row *row_packet = result->row_packet;
DBG_ENTER("mysqlnd_stmt_fetch_row_unbuffered"); DBG_ENTER("mysqlnd_stmt_fetch_row_unbuffered");
@ -712,6 +733,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int
mysqlnd_unbuffered_free_last_data() before it. The function returns always true. mysqlnd_unbuffered_free_last_data() before it. The function returns always true.
*/ */
if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) { if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
unsigned int i, field_count = result->field_count;
result->unbuf->row_count++; result->unbuf->row_count++;
*fetched_anything = TRUE; *fetched_anything = TRUE;
@ -966,7 +988,7 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param, unsigned int fla
/* {{{ mysqlnd_stmt::fetch */ /* {{{ mysqlnd_stmt::fetch */
PHPAPI enum_func_status
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const stmt, MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const stmt,
zend_bool * const fetched_anything TSRMLS_DC) zend_bool * const fetched_anything TSRMLS_DC)
{ {
@ -1021,7 +1043,6 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const stmt TSRMLS_DC) MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const stmt TSRMLS_DC)
{ {
enum_func_status ret = PASS; enum_func_status ret = PASS;
MYSQLND * conn = stmt->conn;
zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */]; zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */];
DBG_ENTER("mysqlnd_stmt::reset"); DBG_ENTER("mysqlnd_stmt::reset");
@ -1031,6 +1052,7 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const stmt TSRMLS_DC)
SET_EMPTY_ERROR(stmt->conn->error_info); SET_EMPTY_ERROR(stmt->conn->error_info);
if (stmt->stmt_id) { if (stmt->stmt_id) {
MYSQLND * conn = stmt->conn;
if (stmt->param_bind) { if (stmt->param_bind) {
unsigned int i; unsigned int i;
DBG_INF("resetting long data"); DBG_INF("resetting long data");
@ -1084,7 +1106,6 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const stmt, unsigned
enum_func_status ret = FAIL; enum_func_status ret = FAIL;
MYSQLND * conn = stmt->conn; MYSQLND * conn = stmt->conn;
zend_uchar *cmd_buf; zend_uchar *cmd_buf;
size_t packet_len;
enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA; enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA;
DBG_ENTER("mysqlnd_stmt::send_long_data"); DBG_ENTER("mysqlnd_stmt::send_long_data");
@ -1126,6 +1147,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const stmt, unsigned
*/ */
if (CONN_GET_STATE(conn) == CONN_READY) { if (CONN_GET_STATE(conn) == CONN_READY) {
size_t packet_len;
stmt->param_bind[param_no].flags |= MYSQLND_PARAM_BIND_BLOB_USED; stmt->param_bind[param_no].flags |= MYSQLND_PARAM_BIND_BLOB_USED;
cmd_buf = mnd_emalloc(packet_len = STMT_ID_LENGTH + 2 + length); cmd_buf = mnd_emalloc(packet_len = STMT_ID_LENGTH + 2 + length);
@ -1178,19 +1200,20 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const stmt, unsigned
/* }}} */ /* }}} */
/* {{{ _mysqlnd_stmt_bind_param */
/* {{{ mysqlnd_stmt::bind_parameters */
static enum_func_status static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_param)(MYSQLND_STMT * const stmt,
MYSQLND_PARAM_BIND * const param_bind TSRMLS_DC)
MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const stmt,
MYSQLND_PARAM_BIND * const param_bind TSRMLS_DC)
{ {
unsigned int i = 0;
DBG_ENTER("mysqlnd_stmt::bind_param"); DBG_ENTER("mysqlnd_stmt::bind_param");
DBG_INF_FMT("stmt=%lu param_count=%u", stmt->stmt_id, stmt->param_count); DBG_INF_FMT("stmt=%lu param_count=%u", stmt->stmt_id, stmt->param_count);
if (stmt->state < MYSQLND_STMT_PREPARED) { if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared"); DBG_ERR("not prepared");
if (param_bind && stmt->param_bind_dtor) {
stmt->param_bind_dtor(param_bind);
}
DBG_RETURN(FAIL); DBG_RETURN(FAIL);
} }
@ -1198,6 +1221,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_param)(MYSQLND_STMT * const stmt,
SET_EMPTY_ERROR(stmt->conn->error_info); SET_EMPTY_ERROR(stmt->conn->error_info);
if (stmt->param_count) { if (stmt->param_count) {
unsigned int i = 0;
if (!param_bind) { if (!param_bind) {
SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
"Re-binding (still) not supported"); "Re-binding (still) not supported");
@ -1210,29 +1235,28 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_param)(MYSQLND_STMT * const stmt,
Forbid for now re-binding!! Forbid for now re-binding!!
*/ */
for (i = 0; i < stmt->param_count; i++) { for (i = 0; i < stmt->param_count; i++) {
/* For BLOBS zv is NULL */
/*
We may have the last reference, then call zval_ptr_dtor()
or we may leak memory.
Switching from bind_one_parameter to bind_parameters may result in zv being NULL
*/
if (stmt->param_bind[i].zv) { if (stmt->param_bind[i].zv) {
/*
We may have the last reference, then call zval_ptr_dtor()
or we may leak memory.
*/
zval_ptr_dtor(&stmt->param_bind[i].zv); zval_ptr_dtor(&stmt->param_bind[i].zv);
stmt->param_bind[i].zv = NULL;
} }
} }
mnd_efree(stmt->param_bind);
if (stmt->param_bind != param_bind && stmt->param_bind_dtor) {
stmt->param_bind_dtor(stmt->param_bind);
}
} }
stmt->param_bind = param_bind; stmt->param_bind = param_bind;
for (i = 0; i < stmt->param_count; i++) { for (i = 0; i < stmt->param_count; i++) {
/* The client will use stmt_send_long_data */ /* The client will use stmt_send_long_data */
DBG_INF_FMT("%d is of type %d", i, stmt->param_bind[i].type); DBG_INF_FMT("%d is of type %d", i, stmt->param_bind[i].type);
if (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB) {
/* Prevent from freeing */
Z_ADDREF_P(stmt->param_bind[i].zv);
/* Don't update is_ref, or we will leak during conversion */
} else {
stmt->param_bind[i].zv = NULL;
/* Prevent from freeing */
/* Don't update is_ref, or we will leak during conversion */
Z_ADDREF_P(stmt->param_bind[i].zv);
if (stmt->param_bind[i].type == MYSQL_TYPE_LONG_BLOB) {
stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED; stmt->param_bind[i].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
} }
} }
@ -1244,7 +1268,58 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_param)(MYSQLND_STMT * const stmt,
/* }}} */ /* }}} */
/* {{{ _mysqlnd_stmt_refresh_bind_param */
/* {{{ mysqlnd_stmt::bind_one_parameter */
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const stmt, unsigned int param_no,
zval * const zv, zend_uchar type TSRMLS_DC)
{
DBG_ENTER("mysqlnd_stmt::bind_one_parameter");
DBG_INF_FMT("stmt=%lu param_no=%d param_count=%u type=%d",
stmt->stmt_id, param_no, stmt->param_count, type);
if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared");
DBG_RETURN(FAIL);
}
if (param_no < 0 || param_no >= stmt->param_count) {
SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
DBG_ERR("invalid param_no");
DBG_RETURN(FAIL);
}
SET_EMPTY_ERROR(stmt->error_info);
SET_EMPTY_ERROR(stmt->conn->error_info);
if (stmt->param_count) {
if (!stmt->param_bind) {
stmt->param_bind = ecalloc(stmt->param_count, sizeof(MYSQLND_PARAM_BIND));
}
/* Prevent from freeing */
/* Don't update is_ref, or we will leak during conversion */
Z_ADDREF_P(zv);
DBG_INF("Binding");
/* Release what we had, if we had */
if (stmt->param_bind[param_no].zv) {
zval_ptr_dtor(&stmt->param_bind[param_no].zv);
}
if (type == MYSQL_TYPE_LONG_BLOB) {
/* The client will use stmt_send_long_data */
stmt->param_bind[param_no].flags &= ~MYSQLND_PARAM_BIND_BLOB_USED;
}
stmt->param_bind[param_no].zv = zv;
stmt->param_bind[param_no].type = type;
stmt->send_types_to_server = 1;
}
DBG_INF("PASS");
DBG_RETURN(PASS);
}
/* }}} */
/* {{{ mysqlnd_stmt::refresh_bind_param */
static enum_func_status static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const stmt TSRMLS_DC) MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const stmt TSRMLS_DC)
{ {
@ -1269,13 +1344,24 @@ MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const stmt TSRML
/* }}} */ /* }}} */
/* {{{ mysqlnd_stmt::set_bind_param_dtor */
static void
MYSQLND_METHOD(mysqlnd_stmt, set_param_bind_dtor)(MYSQLND_STMT * const stmt,
void (*param_bind_dtor)(MYSQLND_PARAM_BIND *dtor) TSRMLS_DC)
{
DBG_ENTER("mysqlnd_stmt::set_bind_param_dtor");
DBG_INF_FMT("stmt=%p", param_bind_dtor);
stmt->param_bind_dtor = param_bind_dtor;
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_stmt::bind_result */ /* {{{ mysqlnd_stmt::bind_result */
static enum_func_status static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt, MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC) MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC)
{ {
uint i = 0;
DBG_ENTER("mysqlnd_stmt::bind_result"); DBG_ENTER("mysqlnd_stmt::bind_result");
DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count); DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count);
@ -1284,14 +1370,16 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
if (stmt->state < MYSQLND_STMT_PREPARED) { if (stmt->state < MYSQLND_STMT_PREPARED) {
SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared); SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
if (result_bind) {
mnd_efree(result_bind);
if (result_bind && stmt->result_bind_dtor) {
stmt->result_bind_dtor(result_bind);
} }
DBG_ERR("not prepared"); DBG_ERR("not prepared");
DBG_RETURN(FAIL); DBG_RETURN(FAIL);
} }
if (stmt->field_count) { if (stmt->field_count) {
uint i = 0;
if (!result_bind) { if (!result_bind) {
DBG_ERR("no result bind passed"); DBG_ERR("no result bind passed");
DBG_RETURN(FAIL); DBG_RETURN(FAIL);
@ -1310,8 +1398,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
*/ */
stmt->result_bind[i].bound = TRUE; stmt->result_bind[i].bound = TRUE;
} }
} else if (result_bind) {
mnd_efree(result_bind);
} else if (result_bind && stmt->result_bind_dtor) {
stmt->result_bind_dtor(result_bind);
} }
DBG_INF("PASS"); DBG_INF("PASS");
DBG_RETURN(PASS); DBG_RETURN(PASS);
@ -1319,6 +1407,19 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const stmt,
/* }}} */ /* }}} */
/* {{{ mysqlnd_stmt::set_bind_result_dtor */
static void
MYSQLND_METHOD(mysqlnd_stmt, set_result_bind_dtor)(MYSQLND_STMT * const stmt,
void (*result_bind_dtor)(MYSQLND_RESULT_BIND *dtor) TSRMLS_DC)
{
DBG_ENTER("mysqlnd_stmt::set_bind_param_dtor");
DBG_INF_FMT("stmt=%p", result_bind_dtor);
stmt->result_bind_dtor = result_bind_dtor;
DBG_VOID_RETURN;
}
/* }}} */
/* {{{ mysqlnd_stmt::insert_id */ /* {{{ mysqlnd_stmt::insert_id */
static uint64 static uint64
MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const stmt) MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const stmt)
@ -1483,7 +1584,8 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const stmt,
case STMT_ATTR_CURSOR_TYPE: { case STMT_ATTR_CURSOR_TYPE: {
if (val > (unsigned long) CURSOR_TYPE_READ_ONLY) { if (val > (unsigned long) CURSOR_TYPE_READ_ONLY) {
SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
return FAIL;
DBG_INF("FAIL");
DBG_RETURN(FAIL);
} }
stmt->flags = val; stmt->flags = val;
break; break;
@ -1493,7 +1595,8 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const stmt,
val = MYSQLND_DEFAULT_PREFETCH_ROWS; val = MYSQLND_DEFAULT_PREFETCH_ROWS;
} else if (val > 1) { } else if (val > 1) {
SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented"); SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
return FAIL;
DBG_INF("FAIL");
DBG_RETURN(FAIL);
} }
stmt->prefetch_rows = val; stmt->prefetch_rows = val;
break; break;
@ -1508,7 +1611,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const stmt,
/* }}} */ /* }}} */
/* {{{ _mysqlnd_stmt_attr_get */
/* {{{ mysqlnd_stmt::attr_get */
static enum_func_status static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, attr_get)(MYSQLND_STMT * const stmt, MYSQLND_METHOD(mysqlnd_stmt, attr_get)(MYSQLND_STMT * const stmt,
enum mysqlnd_stmt_attr attr_type, enum mysqlnd_stmt_attr attr_type,
@ -1624,7 +1727,9 @@ void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC)
} }
} }
} }
mnd_efree(stmt->result_bind);
if (stmt->result_bind_dtor) {
stmt->result_bind_dtor(stmt->result_bind);
}
stmt->result_bind = NULL; stmt->result_bind = NULL;
DBG_VOID_RETURN; DBG_VOID_RETURN;
@ -1649,13 +1754,17 @@ void mysqlnd_internal_free_stmt_content(MYSQLND_STMT *stmt TSRMLS_DC)
lost reference. lost reference.
*/ */
for (i = 0; i < stmt->param_count; i++) { for (i = 0; i < stmt->param_count; i++) {
/* For BLOBs zv is NULL */
/*
If bind_one_parameter was used, but not everything was
bound and nothing was fetched, then some `zv` could be NULL
*/
if (stmt->param_bind[i].zv) { if (stmt->param_bind[i].zv) {
zval_ptr_dtor(&stmt->param_bind[i].zv); zval_ptr_dtor(&stmt->param_bind[i].zv);
} }
} }
mnd_efree(stmt->param_bind);
if (stmt->param_bind_dtor) {
stmt->param_bind_dtor(stmt->param_bind);
}
stmt->param_bind = NULL; stmt->param_bind = NULL;
} }
@ -1790,9 +1899,12 @@ struct st_mysqlnd_stmt_methods mysqlnd_stmt_methods = {
MYSQLND_METHOD(mysqlnd_stmt, fetch), MYSQLND_METHOD(mysqlnd_stmt, fetch),
MYSQLND_METHOD(mysqlnd_stmt, bind_param),
MYSQLND_METHOD(mysqlnd_stmt, bind_parameters),
MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter),
MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param), MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param),
MYSQLND_METHOD(mysqlnd_stmt, set_param_bind_dtor),
MYSQLND_METHOD(mysqlnd_stmt, bind_result), MYSQLND_METHOD(mysqlnd_stmt, bind_result),
MYSQLND_METHOD(mysqlnd_stmt, set_result_bind_dtor),
MYSQLND_METHOD(mysqlnd_stmt, send_long_data), MYSQLND_METHOD(mysqlnd_stmt, send_long_data),
MYSQLND_METHOD(mysqlnd_stmt, param_metadata), MYSQLND_METHOD(mysqlnd_stmt, param_metadata),
MYSQLND_METHOD(mysqlnd_stmt, result_metadata), MYSQLND_METHOD(mysqlnd_stmt, result_metadata),
@ -1835,10 +1947,32 @@ MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND * const conn TSRMLS_DC)
*/ */
stmt->conn = conn->m->get_reference(conn); stmt->conn = conn->m->get_reference(conn);
stmt->m->set_param_bind_dtor(stmt, mysqlnd_efree_param_bind_dtor TSRMLS_CC);
stmt->m->set_result_bind_dtor(stmt, mysqlnd_efree_result_bind_dtor TSRMLS_CC);
DBG_RETURN(stmt); DBG_RETURN(stmt);
} }
/* }}} */ /* }}} */
/* {{{ mysqlnd_efree_param_bind_dtor */
PHPAPI void
mysqlnd_efree_param_bind_dtor(MYSQLND_PARAM_BIND * param_bind)
{
efree(param_bind);
}
/* }}} */
/* {{{ mysqlnd_efree_result_bind_dtor */
PHPAPI void
mysqlnd_efree_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind)
{
efree(result_bind);
}
/* }}} */
/* /*
* Local variables: * Local variables:
* tab-width: 4 * tab-width: 4

114
ext/mysqlnd/mysqlnd_ps_codec.c

@ -156,14 +156,6 @@ void ps_fetch_int8(zval *zv, const MYSQLND_FIELD * const field,
zend_bool as_unicode TSRMLS_DC) zend_bool as_unicode TSRMLS_DC)
{ {
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 1 TSRMLS_CC); ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 1 TSRMLS_CC);
#if 0
if (field->flags & UNSIGNED_FLAG) {
ZVAL_LONG(zv, *(my_uint8*)*row);
} else {
ZVAL_LONG(zv, *(my_int8*)*row);
}
(*row)++;
#endif
} }
/* }}} */ /* }}} */
@ -175,14 +167,6 @@ void ps_fetch_int16(zval *zv, const MYSQLND_FIELD * const field,
zend_bool as_unicode TSRMLS_DC) zend_bool as_unicode TSRMLS_DC)
{ {
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 2 TSRMLS_CC); ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 2 TSRMLS_CC);
#if 0
if (field->flags & UNSIGNED_FLAG) {
ZVAL_LONG(zv, (my_uint16) sint2korr(*row));
} else {
ZVAL_LONG(zv, (my_int16) sint2korr(*row));
}
(*row)+= 2;
#endif
} }
/* }}} */ /* }}} */
@ -194,44 +178,6 @@ void ps_fetch_int32(zval *zv, const MYSQLND_FIELD * const field,
zend_bool as_unicode TSRMLS_DC) zend_bool as_unicode TSRMLS_DC)
{ {
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 4 TSRMLS_CC); ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 4 TSRMLS_CC);
#if 0
if (field->flags & UNSIGNED_FLAG) {
my_uint32 uval;
/* unsigned int (11) */
uval= (my_uint32) sint4korr(*row);
#if SIZEOF_LONG==4
if (uval > INT_MAX) {
char *tmp, *p;
int j=10;
tmp= mnd_emalloc(11);
p= &tmp[9];
do {
*p-- = (uval % 10) + 48;
uval = uval / 10;
} while (--j > 0);
tmp[10]= '\0';
/* unsigned int > INT_MAX is 10 digits - ALWAYS */
#if PHP_MAJOR_VERSION >= 6
if (!as_unicode) {
#endif
ZVAL_STRING(zv, tmp, 0);
#if PHP_MAJOR_VERSION >= 6
} else {
ZVAL_UTF8_STRINGL(zv, tmp, 10, ZSTR_AUTOFREE);
}
#endif /* PHP_MAJOR_VERSION >= 6 */
} else
#endif /* #if SIZEOF_LONG==4 */
{
ZVAL_LONG(zv, uval);
}
} else {
ZVAL_LONG(zv, (my_int32) sint4korr(*row));
}
(*row)+= 4;
#endif /* 0 */
} }
/* }}} */ /* }}} */
@ -243,40 +189,6 @@ void ps_fetch_int64(zval *zv, const MYSQLND_FIELD * const field,
zend_bool as_unicode TSRMLS_DC) zend_bool as_unicode TSRMLS_DC)
{ {
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 8 TSRMLS_CC); ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, as_unicode, 8 TSRMLS_CC);
#if 0
uint64 llval = (uint64) sint8korr(*row);
zend_bool uns = field->flags & UNSIGNED_FLAG? TRUE:FALSE;
#if SIZEOF_LONG==8
if (uns == TRUE && llval > 9223372036854775807L) {
#elif SIZEOF_LONG==4
if ((uns == TRUE && llval > L64(2147483647)) ||
(uns == FALSE && ((L64( 2147483647) < (int64) llval) ||
(L64(-2147483648) > (int64) llval))))
{
#endif
char tmp[22];
/* even though lval is declared as unsigned, the value
* may be negative. Therefor we cannot use MYSQLND_LLU_SPEC and must
* use MYSQLND_LL_SPEC.
*/
sprintf((char *)&tmp, uns == TRUE? MYSQLND_LLU_SPEC : MYSQLND_LL_SPEC, llval);
#if PHP_MAJOR_VERSION >= 6
if (!as_unicode) {
#endif
ZVAL_STRING(zv, tmp, 1);
#if PHP_MAJOR_VERSION >= 6
} else {
ZVAL_UTF8_STRING(zv, tmp, ZSTR_DUPLICATE);
}
#endif
} else {
/* This cast is safe, as we have checked the values above */
ZVAL_LONG(zv, (long) llval);
}
(*row)+= 8;
#endif /* 0 */
} }
/* }}} */ /* }}} */
@ -707,14 +619,15 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
for (i = 0; i < stmt->param_count; i++) { for (i = 0; i < stmt->param_count; i++) {
unsigned int j; unsigned int j;
zval *the_var = stmt->param_bind[i].zv; zval *the_var = stmt->param_bind[i].zv;
if (stmt->param_bind[i].zv &&
Z_TYPE_P(stmt->param_bind[i].zv) == IS_NULL) {
if (!the_var || (stmt->param_bind[i].type != MYSQL_TYPE_LONG_BLOB &&
Z_TYPE_P(the_var) == IS_NULL)) {
continue; continue;
} }
for (j = i + 1; j < stmt->param_count; j++) { for (j = i + 1; j < stmt->param_count; j++) {
if (stmt->param_bind[j].zv == stmt->param_bind[i].zv) {
if (stmt->param_bind[j].zv == the_var) {
/* Double binding of the same zval, make a copy */ /* Double binding of the same zval, make a copy */
mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i);
mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i);
break; break;
} }
} }
@ -722,9 +635,9 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
switch (stmt->param_bind[i].type) { switch (stmt->param_bind[i].type) {
case MYSQL_TYPE_DOUBLE: case MYSQL_TYPE_DOUBLE:
data_size += 8; data_size += 8;
if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_DOUBLE) {
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
if (!copies || !copies[i]) { if (!copies || !copies[i]) {
mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i);
mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i);
} }
} }
break; break;
@ -737,9 +650,9 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
#else #else
#error "Should not happen" #error "Should not happen"
#endif #endif
if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_LONG) {
if (Z_TYPE_P(the_var) != IS_LONG) {
if (!copies || !copies[i]) { if (!copies || !copies[i]) {
mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i);
mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i);
} }
} }
break; break;
@ -748,7 +661,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
/* /*
User hasn't sent anything, we will send empty string. User hasn't sent anything, we will send empty string.
Empty string has length of 0, encoded in 1 byte. No real Empty string has length of 0, encoded in 1 byte. No real
data will follow after it.
data will follows after it.
*/ */
data_size++; data_size++;
} }
@ -756,14 +669,13 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT *stmt, zend_uchar **buf, zend_uch
case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VAR_STRING:
data_size += 8; /* max 8 bytes for size */ data_size += 8; /* max 8 bytes for size */
#if PHP_MAJOR_VERSION < 6 #if PHP_MAJOR_VERSION < 6
if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_STRING)
if (Z_TYPE_P(the_var) != IS_STRING)
#elif PHP_MAJOR_VERSION >= 6 #elif PHP_MAJOR_VERSION >= 6
if (Z_TYPE_P(stmt->param_bind[i].zv) != IS_STRING ||
(UG(unicode) && Z_TYPE_P(stmt->param_bind[i].zv) == IS_UNICODE))
if (Z_TYPE_P(the_var) != IS_STRING || (UG(unicode) && Z_TYPE_P(the_var) == IS_UNICODE))
#endif #endif
{ {
if (!copies || !copies[i]) { if (!copies || !copies[i]) {
mysqlnd_stmt_copy_it(&copies, stmt->param_bind[i].zv, stmt->param_count, i);
mysqlnd_stmt_copy_it(&copies, the_var, stmt->param_count, i);
} }
the_var = copies[i]; the_var = copies[i];
#if PHP_MAJOR_VERSION >= 6 #if PHP_MAJOR_VERSION >= 6

38
ext/mysqlnd/mysqlnd_result.c

@ -194,7 +194,7 @@ void mysqlnd_free_buffered_data(MYSQLND_RES *result TSRMLS_DC)
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row]; MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row];
int col; int col;
for (col = field_count - 1; col >=0 ; col--) {
for (col = field_count - 1; col >= 0; --col) {
zend_bool copy_ctor_called; zend_bool copy_ctor_called;
if (current_row[0] == NULL) { if (current_row[0] == NULL) {
break;/* row that was never initialized */ break;/* row that was never initialized */
@ -518,8 +518,8 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
conn->last_query_type = QUERY_SELECT; conn->last_query_type = QUERY_SELECT;
CONN_SET_STATE(conn, CONN_FETCHING_DATA); CONN_SET_STATE(conn, CONN_FETCHING_DATA);
/* PS has already allocated it */ /* PS has already allocated it */
conn->field_count = rset_header.field_count;
if (!stmt) { if (!stmt) {
conn->field_count = rset_header.field_count;
result = result =
conn->current_result= conn->current_result=
mysqlnd_result_init(rset_header.field_count, mysqlnd_result_init(rset_header.field_count,
@ -533,6 +533,7 @@ mysqlnd_query_read_result_set_header(MYSQLND *conn, MYSQLND_STMT *stmt TSRMLS_DC
prepared statements can't send result set metadata for these queries prepared statements can't send result set metadata for these queries
on prepare stage. Read it now. on prepare stage. Read it now.
*/ */
conn->field_count = rset_header.field_count;
result = result =
stmt->result = stmt->result =
mysqlnd_result_init(rset_header.field_count, mysqlnd_result_init(rset_header.field_count,
@ -816,10 +817,7 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
{ {
enum_func_status ret; enum_func_status ret;
zval *row = (zval *) param; zval *row = (zval *) param;
unsigned int i,
field_count = result->field_count;
php_mysql_packet_row *row_packet = result->row_packet; php_mysql_packet_row *row_packet = result->row_packet;
unsigned long *lengths = result->lengths;
DBG_ENTER("mysqlnd_fetch_row_unbuffered"); DBG_ENTER("mysqlnd_fetch_row_unbuffered");
DBG_INF_FMT("flags=%d", flags); DBG_INF_FMT("flags=%d", flags);
@ -859,10 +857,12 @@ mysqlnd_fetch_row_unbuffered(MYSQLND_RES *result, void *param, unsigned int flag
HashTable *row_ht = Z_ARRVAL_P(row); HashTable *row_ht = Z_ARRVAL_P(row);
MYSQLND_FIELD *field = result->meta->fields; MYSQLND_FIELD *field = result->meta->fields;
struct mysqlnd_field_hash_key *zend_hash_key = result->meta->zend_hash_keys; struct mysqlnd_field_hash_key *zend_hash_key = result->meta->zend_hash_keys;
unsigned int i, field_count = result->field_count;
unsigned long *lengths = result->lengths;
result->m.row_decoder(result->unbuf->last_row_buffer, result->m.row_decoder(result->unbuf->last_row_buffer,
result->unbuf->last_row_data, result->unbuf->last_row_data,
row_packet->field_count,
field_count,
row_packet->fields_metadata, row_packet->fields_metadata,
result->conn TSRMLS_CC); result->conn TSRMLS_CC);
@ -1199,7 +1199,6 @@ mysqlnd_store_result_fetch_data(MYSQLND * const conn, MYSQLND_RES *result,
row_packet->skip_extraction = TRUE; /* let php_mysqlnd_rowp_read() not allocate row_packet->fields, we will do it */ row_packet->skip_extraction = TRUE; /* let php_mysqlnd_rowp_read() not allocate row_packet->fields, we will do it */
while (FAIL != (ret = PACKET_READ(row_packet, conn)) && !row_packet->eof) { while (FAIL != (ret = PACKET_READ(row_packet, conn)) && !row_packet->eof) {
if (!free_rows) { if (!free_rows) {
uint64 total_rows = free_rows = next_extend = next_extend * 5 / 3; /* extend with 33% */ uint64 total_rows = free_rows = next_extend = next_extend * 5 / 3; /* extend with 33% */
total_rows += set->row_count; total_rows += set->row_count;
@ -1312,7 +1311,6 @@ static enum_func_status
mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int flags, mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int flags,
zend_bool *fetched_anything TSRMLS_DC) zend_bool *fetched_anything TSRMLS_DC)
{ {
unsigned int i;
zval *row = (zval *) param; zval *row = (zval *) param;
MYSQLND_RES_BG_BUFFERED *set = result->bg_stored_data; MYSQLND_RES_BG_BUFFERED *set = result->bg_stored_data;
@ -1349,6 +1347,7 @@ mysqlnd_fetch_row_async_buffered(MYSQLND_RES *result, void *param, unsigned int
/* If there was no decoding in background, we have to decode here */ /* If there was no decoding in background, we have to decode here */
if (set->decode_in_foreground == TRUE) { if (set->decode_in_foreground == TRUE) {
MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row_num]; MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row_num];
unsigned int i;
result->m.row_decoder(current_buffer, result->m.row_decoder(current_buffer,
current_row, current_row,
result->meta->field_count, result->meta->field_count,
@ -1713,7 +1712,7 @@ MYSQLND_METHOD(mysqlnd_res, num_fields)(const MYSQLND_RES * const result)
/* {{{ mysqlnd_res::fetch_field */ /* {{{ mysqlnd_res::fetch_field */
static MYSQLND_FIELD *
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC) MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC)
{ {
DBG_ENTER("mysqlnd_res::fetch_field"); DBG_ENTER("mysqlnd_res::fetch_field");
@ -1730,7 +1729,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result TSRMLS_DC)
/* {{{ mysqlnd_res::fetch_field_direct */ /* {{{ mysqlnd_res::fetch_field_direct */
static MYSQLND_FIELD *
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result,
MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC) MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC)
{ {
@ -1748,6 +1747,24 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result,
/* }}} */ /* }}} */
/* {{{ mysqlnd_res::fetch_field */
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res::fetch_fields");
if (result->meta) {
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
/* we have to initialize the rest to get the updated max length */
mysqlnd_res_initialize_result_set_rest(result TSRMLS_CC);
}
DBG_RETURN(result->meta->m->fetch_fields(result->meta TSRMLS_CC));
}
DBG_RETURN(NULL);
}
/* }}} */
/* {{{ mysqlnd_res::field_seek */ /* {{{ mysqlnd_res::field_seek */
static MYSQLND_FIELD_OFFSET static MYSQLND_FIELD_OFFSET
MYSQLND_METHOD(mysqlnd_res, field_seek)(MYSQLND_RES * const result, MYSQLND_METHOD(mysqlnd_res, field_seek)(MYSQLND_RES * const result,
@ -1944,6 +1961,7 @@ MYSQLND_RES *mysqlnd_result_init(unsigned int field_count, MYSQLND_THD_ZVAL_PCAC
ret->m.field_tell = MYSQLND_METHOD(mysqlnd_res, field_tell); ret->m.field_tell = MYSQLND_METHOD(mysqlnd_res, field_tell);
ret->m.fetch_field = MYSQLND_METHOD(mysqlnd_res, fetch_field); ret->m.fetch_field = MYSQLND_METHOD(mysqlnd_res, fetch_field);
ret->m.fetch_field_direct = MYSQLND_METHOD(mysqlnd_res, fetch_field_direct); ret->m.fetch_field_direct = MYSQLND_METHOD(mysqlnd_res, fetch_field_direct);
ret->m.fetch_fields = MYSQLND_METHOD(mysqlnd_res, fetch_fields);
ret->m.skip_result = MYSQLND_METHOD(mysqlnd_res, skip_result); ret->m.skip_result = MYSQLND_METHOD(mysqlnd_res, skip_result);
ret->m.free_result_buffers = MYSQLND_METHOD(mysqlnd_res, free_result_buffers); ret->m.free_result_buffers = MYSQLND_METHOD(mysqlnd_res, free_result_buffers);

18
ext/mysqlnd/mysqlnd_result_meta.c

@ -369,7 +369,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * co
/* }}} */ /* }}} */
/* {{{ mysqlnd_res_meta::fetch_field */ /* {{{ mysqlnd_res_meta::fetch_field */
static MYSQLND_FIELD *
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC) MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC)
{ {
DBG_ENTER("mysqlnd_res_meta::fetch_field"); DBG_ENTER("mysqlnd_res_meta::fetch_field");
@ -382,7 +382,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, fetch_field)(MYSQLND_RES_METADATA * const meta
/* {{{ mysqlnd_res_meta::fetch_field_direct */ /* {{{ mysqlnd_res_meta::fetch_field_direct */
static MYSQLND_FIELD *
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct)(const MYSQLND_RES_METADATA * const meta,
MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC) MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC)
{ {
@ -393,6 +393,16 @@ MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct)(const MYSQLND_RES_METADATA
/* }}} */ /* }}} */
/* {{{ mysqlnd_res_meta::fetch_fields */
static const MYSQLND_FIELD *
MYSQLND_METHOD(mysqlnd_res_meta, fetch_fields)(MYSQLND_RES_METADATA * const meta TSRMLS_DC)
{
DBG_ENTER("mysqlnd_res_meta::fetch_fields");
DBG_RETURN(meta->fields);
}
/* }}} */
/* {{{ mysqlnd_res_meta::field_tell */ /* {{{ mysqlnd_res_meta::field_tell */
static MYSQLND_FIELD_OFFSET static MYSQLND_FIELD_OFFSET
MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const meta) MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const meta)
@ -405,6 +415,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, field_tell)(const MYSQLND_RES_METADATA * const
MYSQLND_CLASS_METHODS_START(mysqlnd_res_meta) MYSQLND_CLASS_METHODS_START(mysqlnd_res_meta)
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field), MYSQLND_METHOD(mysqlnd_res_meta, fetch_field),
MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct), MYSQLND_METHOD(mysqlnd_res_meta, fetch_field_direct),
MYSQLND_METHOD(mysqlnd_res_meta, fetch_fields),
MYSQLND_METHOD(mysqlnd_res_meta, field_tell), MYSQLND_METHOD(mysqlnd_res_meta, field_tell),
MYSQLND_METHOD(mysqlnd_res_meta, read_metadata), MYSQLND_METHOD(mysqlnd_res_meta, read_metadata),
MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata), MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata),
@ -413,7 +424,8 @@ MYSQLND_CLASS_METHODS_END;
/* {{{ mysqlnd_result_meta_init */ /* {{{ mysqlnd_result_meta_init */
MYSQLND_RES_METADATA *mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC)
MYSQLND_RES_METADATA *
mysqlnd_result_meta_init(unsigned int field_count TSRMLS_DC)
{ {
MYSQLND_RES_METADATA *ret; MYSQLND_RES_METADATA *ret;
DBG_ENTER("mysqlnd_result_meta_init"); DBG_ENTER("mysqlnd_result_meta_init");

80
ext/mysqlnd/mysqlnd_structs.h

@ -92,10 +92,10 @@ typedef struct st_mysqlnd_field
typedef struct st_mysqlnd_upsert_result typedef struct st_mysqlnd_upsert_result
{ {
unsigned int warning_count;
unsigned int server_status;
uint64 affected_rows;
uint64 last_insert_id;
unsigned int warning_count;
unsigned int server_status;
uint64 affected_rows;
uint64 last_insert_id;
} mysqlnd_upsert_status; } mysqlnd_upsert_status;
@ -212,7 +212,7 @@ typedef struct st_mysqlnd_stats
{ {
uint64 values[STAT_LAST]; uint64 values[STAT_LAST];
#ifdef ZTS #ifdef ZTS
MUTEX_T LOCK_access;
MUTEX_T LOCK_access;
#endif #endif
} MYSQLND_STATS; } MYSQLND_STATS;
@ -257,7 +257,7 @@ struct st_mysqlnd_conn_methods
unsigned int (*get_error_no)(const MYSQLND * const conn); unsigned int (*get_error_no)(const MYSQLND * const conn);
const char * (*get_error_str)(const MYSQLND * const conn); const char * (*get_error_str)(const MYSQLND * const conn);
const char * (*get_sqlstate)(const MYSQLND * const conn); const char * (*get_sqlstate)(const MYSQLND * const conn);
uint64 (*get_thread_id)(const MYSQLND * const conn);
uint64 (*get_thread_id)(const MYSQLND * const conn);
void (*get_statistics)(const MYSQLND * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC); void (*get_statistics)(const MYSQLND * const conn, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
unsigned long (*get_server_version)(const MYSQLND * const conn); unsigned long (*get_server_version)(const MYSQLND * const conn);
@ -270,8 +270,8 @@ struct st_mysqlnd_conn_methods
MYSQLND_RES * (*list_fields)(MYSQLND *conn, const char *table, const char *achtung_wild TSRMLS_DC); MYSQLND_RES * (*list_fields)(MYSQLND *conn, const char *table, const char *achtung_wild TSRMLS_DC);
MYSQLND_RES * (*list_method)(MYSQLND *conn, const char *query, const char *achtung_wild, char *par1 TSRMLS_DC); MYSQLND_RES * (*list_method)(MYSQLND *conn, const char *query, const char *achtung_wild, char *par1 TSRMLS_DC);
uint64 (*get_last_insert_id)(const MYSQLND * const conn);
uint64 (*get_affected_rows)(const MYSQLND * const conn);
uint64 (*get_last_insert_id)(const MYSQLND * const conn);
uint64 (*get_affected_rows)(const MYSQLND * const conn);
unsigned int (*get_warning_count)(const MYSQLND * const conn); unsigned int (*get_warning_count)(const MYSQLND * const conn);
unsigned int (*get_field_count)(const MYSQLND * const conn); unsigned int (*get_field_count)(const MYSQLND * const conn);
@ -302,14 +302,15 @@ struct st_mysqlnd_res_methods
MYSQLND_ROW_C (*fetch_row_c)(MYSQLND_RES *result TSRMLS_DC); MYSQLND_ROW_C (*fetch_row_c)(MYSQLND_RES *result TSRMLS_DC);
void (*fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC); void (*fetch_all)(MYSQLND_RES *result, unsigned int flags, zval *return_value TSRMLS_DC ZEND_FILE_LINE_DC);
void (*fetch_field_data)(MYSQLND_RES *result, unsigned int offset, zval *return_value TSRMLS_DC); void (*fetch_field_data)(MYSQLND_RES *result, unsigned int offset, zval *return_value TSRMLS_DC);
uint64 (*num_rows)(const MYSQLND_RES * const result);
uint64 (*num_rows)(const MYSQLND_RES * const result);
unsigned int (*num_fields)(const MYSQLND_RES * const result); unsigned int (*num_fields)(const MYSQLND_RES * const result);
enum_func_status (*skip_result)(MYSQLND_RES * const result TSRMLS_DC); enum_func_status (*skip_result)(MYSQLND_RES * const result TSRMLS_DC);
enum_func_status (*seek_data)(MYSQLND_RES * result, uint64 row TSRMLS_DC); enum_func_status (*seek_data)(MYSQLND_RES * result, uint64 row TSRMLS_DC);
MYSQLND_FIELD_OFFSET (*seek_field)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset); MYSQLND_FIELD_OFFSET (*seek_field)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET field_offset);
MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES * const result); MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES * const result);
MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES * const result TSRMLS_DC);
MYSQLND_FIELD * (*fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
const MYSQLND_FIELD *(*fetch_field)(MYSQLND_RES * const result TSRMLS_DC);
const MYSQLND_FIELD *(*fetch_field_direct)(MYSQLND_RES * const result, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
const MYSQLND_FIELD *(*fetch_fields)(MYSQLND_RES * const result TSRMLS_DC);
enum_func_status (*read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn TSRMLS_DC); enum_func_status (*read_result_metadata)(MYSQLND_RES *result, MYSQLND *conn TSRMLS_DC);
unsigned long * (*fetch_lengths)(MYSQLND_RES * const result); unsigned long * (*fetch_lengths)(MYSQLND_RES * const result);
@ -325,8 +326,9 @@ struct st_mysqlnd_res_methods
struct st_mysqlnd_res_meta_methods struct st_mysqlnd_res_meta_methods
{ {
MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC);
MYSQLND_FIELD * (*fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
const MYSQLND_FIELD * (*fetch_field)(MYSQLND_RES_METADATA * const meta TSRMLS_DC);
const MYSQLND_FIELD * (*fetch_field_direct)(const MYSQLND_RES_METADATA * const meta, MYSQLND_FIELD_OFFSET fieldnr TSRMLS_DC);
const MYSQLND_FIELD * (*fetch_fields)(MYSQLND_RES_METADATA * const meta TSRMLS_DC);
MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES_METADATA * const meta); MYSQLND_FIELD_OFFSET (*field_tell)(const MYSQLND_RES_METADATA * const meta);
enum_func_status (*read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC); enum_func_status (*read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND *conn TSRMLS_DC);
MYSQLND_RES_METADATA * (*clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent TSRMLS_DC); MYSQLND_RES_METADATA * (*clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent TSRMLS_DC);
@ -350,17 +352,20 @@ struct st_mysqlnd_stmt_methods
enum_func_status (*fetch)(MYSQLND_STMT * const stmt, zend_bool * const fetched_anything TSRMLS_DC); enum_func_status (*fetch)(MYSQLND_STMT * const stmt, zend_bool * const fetched_anything TSRMLS_DC);
enum_func_status (*bind_param)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * const param_bind TSRMLS_DC);
enum_func_status (*bind_parameters)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * const param_bind TSRMLS_DC);
enum_func_status (*bind_one_parameter)(MYSQLND_STMT * const stmt, unsigned int param_no, zval * const zv, zend_uchar type TSRMLS_DC);
enum_func_status (*refresh_bind_param)(MYSQLND_STMT * const stmt TSRMLS_DC); enum_func_status (*refresh_bind_param)(MYSQLND_STMT * const stmt TSRMLS_DC);
void (*set_param_bind_dtor)(MYSQLND_STMT * const stmt, void (*param_bind_dtor)(MYSQLND_PARAM_BIND *) TSRMLS_DC);
enum_func_status (*bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC); enum_func_status (*bind_result)(MYSQLND_STMT * const stmt, MYSQLND_RESULT_BIND * const result_bind TSRMLS_DC);
void (*set_result_bind_dtor)(MYSQLND_STMT * const stmt, void (*result_bind_dtor)(MYSQLND_RESULT_BIND *) TSRMLS_DC);
enum_func_status (*send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num, enum_func_status (*send_long_data)(MYSQLND_STMT * const stmt, unsigned int param_num,
const char * const data, unsigned long length TSRMLS_DC); const char * const data, unsigned long length TSRMLS_DC);
MYSQLND_RES * (*get_parameter_metadata)(MYSQLND_STMT * const stmt);
MYSQLND_RES * (*get_result_metadata)(MYSQLND_STMT * const stmt TSRMLS_DC);
MYSQLND_RES * (*get_parameter_metadata)(MYSQLND_STMT * const stmt);
MYSQLND_RES * (*get_result_metadata)(MYSQLND_STMT * const stmt TSRMLS_DC);
uint64 (*get_last_insert_id)(const MYSQLND_STMT * const stmt);
uint64 (*get_affected_rows)(const MYSQLND_STMT * const stmt);
uint64 (*get_num_rows)(const MYSQLND_STMT * const stmt);
uint64 (*get_last_insert_id)(const MYSQLND_STMT * const stmt);
uint64 (*get_affected_rows)(const MYSQLND_STMT * const stmt);
uint64 (*get_num_rows)(const MYSQLND_STMT * const stmt);
unsigned int (*get_param_count)(const MYSQLND_STMT * const stmt); unsigned int (*get_param_count)(const MYSQLND_STMT * const stmt);
unsigned int (*get_field_count)(const MYSQLND_STMT * const stmt); unsigned int (*get_field_count)(const MYSQLND_STMT * const stmt);
@ -387,7 +392,7 @@ struct st_mysqlnd_connection
char *passwd; char *passwd;
unsigned int *passwd_len; unsigned int *passwd_len;
char *scheme; char *scheme;
uint64 thread_id;
uint64 thread_id;
char *server_version; char *server_version;
char *host_info; char *host_info;
unsigned char *scramble; unsigned char *scramble;
@ -493,22 +498,22 @@ struct st_mysqlnd_result_metadata
struct st_mysqlnd_background_buffered_result struct st_mysqlnd_background_buffered_result
{ {
zval ***data;
uint64 data_size;
zval ***data_cursor;
zval ***data;
uint64 data_size;
zval ***data_cursor;
MYSQLND_MEMORY_POOL_CHUNK **row_buffers; MYSQLND_MEMORY_POOL_CHUNK **row_buffers;
uint64 row_count;
uint64 initialized_rows;
zend_bool persistent;
uint64 row_count;
uint64 initialized_rows;
zend_bool persistent;
MYSQLND_QCACHE *qcache;
unsigned int references;
MYSQLND_QCACHE *qcache;
unsigned int references;
zend_bool decode_in_foreground;
zend_bool decode_in_foreground;
#ifdef ZTS #ifdef ZTS
zend_bool bg_fetch_finished;
MUTEX_T LOCK;
zend_bool bg_fetch_finished;
MUTEX_T LOCK;
#endif #endif
mysqlnd_error_info error_info; mysqlnd_error_info error_info;
@ -521,8 +526,8 @@ struct st_mysqlnd_buffered_result
zval **data; zval **data;
zval **data_cursor; zval **data_cursor;
MYSQLND_MEMORY_POOL_CHUNK **row_buffers; MYSQLND_MEMORY_POOL_CHUNK **row_buffers;
uint64 row_count;
uint64 initialized_rows;
uint64 row_count;
uint64 initialized_rows;
zend_bool persistent; zend_bool persistent;
MYSQLND_QCACHE *qcache; MYSQLND_QCACHE *qcache;
@ -538,7 +543,7 @@ struct st_mysqlnd_unbuffered_result
zval **last_row_data; zval **last_row_data;
MYSQLND_MEMORY_POOL_CHUNK *last_row_buffer; MYSQLND_MEMORY_POOL_CHUNK *last_row_buffer;
uint64 row_count;
uint64 row_count;
zend_bool eof_reached; zend_bool eof_reached;
}; };
@ -565,10 +570,10 @@ struct st_mysqlnd_res
*/ */
unsigned long *lengths; unsigned long *lengths;
php_mysql_packet_row *row_packet; /* Unused for PS */
php_mysql_packet_row *row_packet;
/* zval cache */ /* zval cache */
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
MYSQLND_THD_ZVAL_PCACHE *zval_cache;
}; };
@ -615,6 +620,9 @@ struct st_mysqlnd_stmt
MYSQLND_CMD_BUFFER cmd_buffer; MYSQLND_CMD_BUFFER cmd_buffer;
unsigned int execute_count;/* count how many times the stmt was executed */ unsigned int execute_count;/* count how many times the stmt was executed */
void (*param_bind_dtor)(MYSQLND_PARAM_BIND *);
void (*result_bind_dtor)(MYSQLND_RESULT_BIND *);
struct st_mysqlnd_stmt_methods *m; struct st_mysqlnd_stmt_methods *m;
}; };

10
ext/mysqlnd/mysqlnd_wireprotocol.c

@ -529,7 +529,7 @@ static enum_func_status
php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC) php_mysqlnd_greet_read(void *_packet, MYSQLND *conn TSRMLS_DC)
{ {
zend_uchar buf[512]; zend_uchar buf[512];
zend_uchar *p= buf;
zend_uchar *p = buf;
zend_uchar *begin = buf; zend_uchar *begin = buf;
php_mysql_packet_greet *packet= (php_mysql_packet_greet *) _packet; php_mysql_packet_greet *packet= (php_mysql_packet_greet *) _packet;
@ -623,7 +623,7 @@ void php_mysqlnd_greet_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
static static
void php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len) void php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
{ {
const unsigned char *s1_end= s1 + len;
const unsigned char *s1_end = s1 + len;
while (s1 < s1_end) { while (s1 < s1_end) {
*buffer++= *s1++ ^ *s2++; *buffer++= *s1++ ^ *s2++;
} }
@ -754,7 +754,7 @@ php_mysqlnd_ok_read(void *_packet, MYSQLND *conn TSRMLS_DC)
PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "OK"); PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "OK");
/* Should be always 0x0 or 0xFF for error */ /* Should be always 0x0 or 0xFF for error */
packet->field_count= uint1korr(p);
packet->field_count = uint1korr(p);
p++; p++;
if (0xFF == packet->field_count) { if (0xFF == packet->field_count) {
@ -825,7 +825,7 @@ php_mysqlnd_eof_read(void *_packet, MYSQLND *conn TSRMLS_DC)
*/ */
php_mysql_packet_eof *packet= (php_mysql_packet_eof *) _packet; php_mysql_packet_eof *packet= (php_mysql_packet_eof *) _packet;
zend_uchar buf[5 + 10 + sizeof(packet->sqlstate) + sizeof(packet->error)]; zend_uchar buf[5 + 10 + sizeof(packet->sqlstate) + sizeof(packet->error)];
zend_uchar *p= buf;
zend_uchar *p = buf;
zend_uchar *begin = buf; zend_uchar *begin = buf;
DBG_ENTER("php_mysqlnd_eof_read"); DBG_ENTER("php_mysqlnd_eof_read");
@ -833,7 +833,7 @@ php_mysqlnd_eof_read(void *_packet, MYSQLND *conn TSRMLS_DC)
PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "EOF"); PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "EOF");
/* Should be always 0xFE */ /* Should be always 0xFE */
packet->field_count= uint1korr(p);
packet->field_count = uint1korr(p);
p++; p++;
if (0xFF == packet->field_count) { if (0xFF == packet->field_count) {

2
ext/mysqlnd/php_mysqlnd.c

@ -199,8 +199,10 @@ static PHP_RINIT_FUNCTION(mysqlnd)
return SUCCESS; return SUCCESS;
} }
/* }}} */ /* }}} */
#endif
#if defined(PHP_DEBUG)
/* {{{ PHP_RSHUTDOWN_FUNCTION /* {{{ PHP_RSHUTDOWN_FUNCTION
*/ */
static PHP_RSHUTDOWN_FUNCTION(mysqlnd) static PHP_RSHUTDOWN_FUNCTION(mysqlnd)

Loading…
Cancel
Save