diff options
Diffstat (limited to 'ext/mysqli/mysqli_api.c')
| -rw-r--r-- | ext/mysqli/mysqli_api.c | 1043 |
1 files changed, 629 insertions, 414 deletions
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index fd01ba9ffa..5e55be7d51 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -12,7 +12,9 @@ | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ - | Author: Georg Richter <georg@php.net> | + | Authors: Georg Richter <georg@php.net> | + | Andrey Hristov <andrey@php.net> | + | Ulf Wendel <uw@php.net> | +----------------------------------------------------------------------+ $Id$ @@ -26,8 +28,9 @@ #include "php.h" #include "php_ini.h" +#include "php_globals.h" #include "ext/standard/info.h" -#include "php_mysqli.h" +#include "php_mysqli_structs.h" /* {{{ proto mixed mysqli_affected_rows(object link) Get number of affected rows in previous MySQL operation */ @@ -51,16 +54,17 @@ PHP_FUNCTION(mysqli_affected_rows) } /* }}} */ + /* {{{ proto bool mysqli_autocommit(object link, bool mode) Turn auto commit on or of */ PHP_FUNCTION(mysqli_autocommit) { - MY_MYSQL *mysql; - zval *mysql_link; - zend_bool automode; + MY_MYSQL *mysql; + zval *mysql_link; + zend_bool automode; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ob", &mysql_link, mysqli_link_class_entry, &automode) == FAILURE) { - return; + return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); @@ -71,83 +75,38 @@ PHP_FUNCTION(mysqli_autocommit) } /* }}} */ -/* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed,....]) - Bind variables to a prepared statement as parameters */ -PHP_FUNCTION(mysqli_stmt_bind_param) +/* {{{ mysqli_stmt_bind_param_do_bind */ +#ifndef HAVE_MYSQLND +static +int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars, + zval ***args, unsigned int start, const char * const types TSRMLS_DC) { - zval ***args; - int argc = ZEND_NUM_ARGS(); - int i; - int num_vars; - int start = 2; - int ofs; - MY_STMT *stmt; - zval *mysql_stmt; + int i, ofs; MYSQL_BIND *bind; - char *types; - int typelen; unsigned long rc; - /* calculate and check number of parameters */ - if (argc < 2) { - /* there has to be at least one pair */ - WRONG_PARAM_COUNT; - } - - if (zend_parse_method_parameters((getThis()) ? 1:2 TSRMLS_CC, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, &types, &typelen) == FAILURE) { - return; - } - - MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); - - num_vars = argc - 1; - if (getThis()) { - start = 1; - } else { - /* ignore handle parameter in procedural interface*/ - --num_vars; - } - - if (typelen != argc - start) { - /* number of bind variables doesn't match number of elements in type definition string */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables"); - RETURN_FALSE; - } - - if (typelen != stmt->stmt->param_count) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement"); - RETURN_FALSE; - } - /* prevent leak if variables are already bound */ if (stmt->param.var_cnt) { php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE); } - args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); - - if (zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; - } - stmt->param.is_null = ecalloc(num_vars, sizeof(char)); - bind = (MYSQL_BIND *)ecalloc(num_vars, sizeof(MYSQL_BIND)); + bind = (MYSQL_BIND *) ecalloc(num_vars, sizeof(MYSQL_BIND)); ofs = 0; - for (i=start; i < argc; i++) { + for (i = start; i < argc; i++) { /* set specified type */ switch (types[ofs]) { case 'd': /* Double */ bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE; - bind[ofs].buffer = (char*)&Z_DVAL_PP(args[i]); + bind[ofs].buffer = &Z_DVAL_PP(args[i]); bind[ofs].is_null = &stmt->param.is_null[ofs]; break; case 'i': /* Integer */ - bind[ofs].buffer_type = MYSQL_TYPE_LONG; - bind[ofs].buffer = (char*)&Z_LVAL_PP(args[i]); + bind[ofs].buffer_type = (sizeof(long) > 4) ? MYSQL_TYPE_LONGLONG : MYSQL_TYPE_LONG; + bind[ofs].buffer = &Z_LVAL_PP(args[i]); bind[ofs].is_null = &stmt->param.is_null[ofs]; break; @@ -164,85 +123,162 @@ PHP_FUNCTION(mysqli_stmt_bind_param) default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[ofs], i+1); - RETVAL_FALSE; - goto end; + rc = 1; + goto end_1; } ofs++; } rc = mysql_stmt_bind_param(stmt->stmt, bind); - MYSQLI_REPORT_STMT_ERROR(stmt->stmt); +end_1: if (rc) { - RETVAL_FALSE; - goto end; + efree(stmt->param.is_null); + } else { + stmt->param.var_cnt = num_vars; + stmt->param.vars = (zval **)safe_emalloc(num_vars, sizeof(zval), 0); + for (i = 0; i < num_vars; i++) { + if (bind[i].buffer_type != MYSQL_TYPE_LONG_BLOB) { + ZVAL_ADDREF(*args[i+start]); + stmt->param.vars[i] = *args[i+start]; + } else { + stmt->param.vars[i] = NULL; + } + } } + efree(bind); - stmt->param.var_cnt = num_vars; - stmt->param.vars = (zval **)safe_emalloc(num_vars, sizeof(zval), 0); - for (i = 0; i < num_vars; i++) { - if (bind[i].buffer_type != MYSQL_TYPE_LONG_BLOB) { - ZVAL_ADDREF(*args[i+start]); - stmt->param.vars[i] = *args[i+start]; - } else { - stmt->param.vars[i] = NULL; + return rc; +} +#else +static +int mysqli_stmt_bind_param_do_bind(MY_STMT *stmt, unsigned int argc, unsigned int num_vars, + zval ***args, unsigned int start, const char * const types TSRMLS_DC) +{ + int i; + MYSQLND_PARAM_BIND *params; + enum_func_status ret = FAIL; + + /* If no params -> skip binding and return directly */ + if (argc == start) { + return PASS; + } + params = emalloc((argc - start) * sizeof(MYSQLND_PARAM_BIND)); + for (i = 0; i < (argc - start); i++) { + zend_uchar type; + switch (types[i]) { + case 'd': /* Double */ + type = MYSQL_TYPE_DOUBLE; + break; + case 'i': /* Integer */ +#if SIZEOF_LONG==8 + type = MYSQL_TYPE_LONGLONG; +#elif SIZEOF_LONG==4 + type = MYSQL_TYPE_LONG; +#endif + break; + case 'b': /* Blob (send data) */ + type = MYSQL_TYPE_LONG_BLOB; + break; + case 's': /* string */ + type = MYSQL_TYPE_VAR_STRING; + break; + default: + /* We count parameters from 1 */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Undefined fieldtype %c (parameter %d)", types[i], i + start + 1); + ret = FAIL; + efree(params); + goto end; } + params[i].zv = *(args[i + start]); + params[i].type = type; } - RETVAL_TRUE; + ret = mysqlnd_stmt_bind_param(stmt->stmt, params); + end: - efree(args); - efree(bind); + return ret; } +#endif /* }}} */ -/* {{{ proto bool mysqli_stmt_bind_result(object stmt, mixed var, [,mixed, ...]) - Bind variables to a prepared statement for result storage */ - -/* TODO: - do_alloca, free_alloca -*/ - -PHP_FUNCTION(mysqli_stmt_bind_result) +/* {{{ proto bool mysqli_stmt_bind_param(object stmt, string types, mixed variable [,mixed,....]) U + Bind variables to a prepared statement as parameters */ +PHP_FUNCTION(mysqli_stmt_bind_param) { - zval ***args; - int argc = ZEND_NUM_ARGS(); - int i; - int start = 1; - int var_cnt; - int ofs; - long col_type; - ulong rc; - MY_STMT *stmt; - zval *mysql_stmt; - MYSQL_BIND *bind; + zval ***args; + int argc = ZEND_NUM_ARGS(); + int num_vars; + int start = 2; + MY_STMT *stmt; + zval *mysql_stmt; + char *types; + int types_len; + unsigned long rc; - if (getThis()) { - start = 0; + /* calculate and check number of parameters */ + if (argc < 2) { + /* there has to be at least one pair */ + WRONG_PARAM_COUNT; } - if (zend_parse_method_parameters((getThis()) ? 0:1 TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { + if (zend_parse_method_parameters((getThis()) ? 1:2 TSRMLS_CC, getThis(), "Os", &mysql_stmt, mysqli_stmt_class_entry, + &types, &types_len) == FAILURE) { return; } - MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); + MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); - if (argc < (getThis() ? 1 : 2)) { - WRONG_PARAM_COUNT; + num_vars = argc - 1; + if (getThis()) { + start = 1; + } else { + /* ignore handle parameter in procedural interface*/ + --num_vars; + } + if (!types_len) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid type or no types specified"); + RETURN_FALSE; + } + + if (types_len != argc - start) { + /* number of bind variables doesn't match number of elements in type definition string */ + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables"); + RETURN_FALSE; + } + + if (types_len != mysql_stmt_param_count(stmt->stmt)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement"); + RETURN_FALSE; } args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); if (zend_get_parameters_array_ex(argc, args) == FAILURE) { - efree(args); - WRONG_PARAM_COUNT; + zend_wrong_param_count(TSRMLS_C); + rc = 1; + } else { + rc = mysqli_stmt_bind_param_do_bind(stmt, argc, num_vars, args, start, types TSRMLS_CC); + MYSQLI_REPORT_STMT_ERROR(stmt->stmt); } - var_cnt = argc - start; + efree(args); - if (var_cnt != mysql_stmt_field_count(stmt->stmt)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement"); - efree(args); - RETURN_FALSE; - } + RETURN_BOOL(!rc); +} +/* }}} */ + +/* {{{ mysqli_stmt_bind_result_do_bind */ +#ifndef HAVE_MYSQLND +/* TODO: + do_alloca, free_alloca +*/ +static int +mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC) +{ + MYSQL_BIND *bind; + int i, ofs; + int var_cnt = argc - start; + long col_type; + ulong rc; /* prevent leak if variables are already bound */ if (stmt->result.var_cnt) { @@ -268,7 +304,7 @@ PHP_FUNCTION(mysqli_stmt_bind_result) convert_to_double_ex(args[i]); stmt->result.buf[ofs].type = IS_DOUBLE; stmt->result.buf[ofs].buflen = sizeof(double); - + /* allocate buffer for double */ stmt->result.buf[ofs].val = (char *)emalloc(sizeof(double)); bind[ofs].buffer_type = MYSQL_TYPE_DOUBLE; @@ -305,7 +341,7 @@ PHP_FUNCTION(mysqli_stmt_bind_result) break; case MYSQL_TYPE_LONGLONG: -#if MYSQL_VERSION_ID > 50002 +#if MYSQL_VERSION_ID > 50002 || defined(HAVE_MYSQLND) case MYSQL_TYPE_BIT: #endif stmt->result.buf[ofs].type = IS_STRING; @@ -324,8 +360,8 @@ PHP_FUNCTION(mysqli_stmt_bind_result) case MYSQL_TYPE_NEWDATE: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_STRING: - case MYSQL_TYPE_BLOB: case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_TIMESTAMP: @@ -385,7 +421,6 @@ PHP_FUNCTION(mysqli_stmt_bind_result) } /* Don't free stmt->result.is_null because is_null & buf are one block of memory */ efree(stmt->result.buf); - RETVAL_FALSE; } else { stmt->result.var_cnt = var_cnt; stmt->result.vars = (zval **)safe_emalloc((var_cnt), sizeof(zval), 0); @@ -394,10 +429,69 @@ PHP_FUNCTION(mysqli_stmt_bind_result) ZVAL_ADDREF(*args[i]); stmt->result.vars[ofs] = *args[i]; } - RETVAL_TRUE; } - efree(args); efree(bind); + + return rc; +} +#else +static int +mysqli_stmt_bind_result_do_bind(MY_STMT *stmt, zval ***args, unsigned int argc, unsigned int start TSRMLS_DC) +{ + unsigned int i; + MYSQLND_RESULT_BIND *params; + + params = emalloc((argc - start) * sizeof(MYSQLND_RESULT_BIND)); + for (i = 0; i < (argc - start); i++) { + params[i].zv = *(args[i + start]); + } + return mysqlnd_stmt_bind_result(stmt->stmt, params); +} +#endif +/* }}} */ + +/* {{{ proto bool mysqli_stmt_bind_result(object stmt, mixed var, [,mixed, ...]) U + Bind variables to a prepared statement for result storage */ +PHP_FUNCTION(mysqli_stmt_bind_result) +{ + zval ***args; + int argc = ZEND_NUM_ARGS(); + int start = 1; + ulong rc; + MY_STMT *stmt; + zval *mysql_stmt; + + if (getThis()) { + start = 0; + } + + if (zend_parse_method_parameters((getThis()) ? 0:1 TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { + return; + } + + MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); + + if (argc < (getThis() ? 1 : 2)) { + WRONG_PARAM_COUNT; + } + + if ((argc - start) != mysql_stmt_field_count(stmt->stmt)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement"); + RETURN_FALSE; + } + + args = (zval ***)safe_emalloc(argc, sizeof(zval **), 0); + + if (zend_get_parameters_array_ex(argc, args) == FAILURE) { + efree(args); + WRONG_PARAM_COUNT; + } + + rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc, start TSRMLS_CC); + + efree(args); + + RETURN_BOOL(!rc); } /* }}} */ @@ -406,9 +500,9 @@ PHP_FUNCTION(mysqli_stmt_bind_result) PHP_FUNCTION(mysqli_change_user) { MY_MYSQL *mysql; - zval *mysql_link = NULL; - char *user, *password, *dbname; - int user_len, password_len, dbname_len; + zval *mysql_link = NULL; + char *user, *password, *dbname; + int user_len, password_len, dbname_len; ulong rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osss", &mysql_link, mysqli_link_class_entry, &user, &user_len, &password, &password_len, &dbname, &dbname_len) == FAILURE) { @@ -431,8 +525,8 @@ PHP_FUNCTION(mysqli_change_user) Returns the name of the character set used for this connection */ PHP_FUNCTION(mysqli_character_set_name) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -440,7 +534,7 @@ PHP_FUNCTION(mysqli_character_set_name) MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - RETURN_STRING((char *) mysql_character_set_name(mysql->mysql), 1); + RETURN_STRING((char *)mysql_character_set_name(mysql->mysql), 1); } /* }}} */ @@ -448,8 +542,8 @@ PHP_FUNCTION(mysqli_character_set_name) Close connection */ PHP_FUNCTION(mysqli_close) { - zval *mysql_link; - MY_MYSQL *mysql; + zval *mysql_link; + MY_MYSQL *mysql; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -457,11 +551,32 @@ PHP_FUNCTION(mysqli_close) MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED); - mysql_close(mysql->mysql); - mysql->mysql = NULL; + if (!mysql->persistent) { + mysqli_close(mysql->mysql, MYSQLI_CLOSE_EXPLICIT); + mysql->mysql = NULL; + } else { + zend_rsrc_list_entry *le; + if (zend_hash_find(&EG(persistent_list), mysql->hash_key, strlen(mysql->hash_key) + 1, (void **)&le) == SUCCESS) { + if (Z_TYPE_P(le) == php_le_pmysqli()) { + mysqli_plist_entry *plist = (mysqli_plist_entry *) le->ptr; + dtor_func_t pDestructor = plist->used_links.pDestructor; + + plist->used_links.pDestructor = NULL; /* Don't call pDestructor now */ + zend_hash_index_del(&plist->used_links, mysql->hash_index); + plist->used_links.pDestructor = pDestructor; /* Restore the destructor */ + + zend_hash_next_index_insert(&plist->free_links, &mysql->mysql, sizeof(MYSQL *), NULL); + MyG(num_links)--; + MyG(num_active_persistent)--; + MyG(num_inactive_persistent)++; + } + } + } + php_clear_mysql(mysql); + + MYSQLI_CLEAR_RESOURCE(&mysql_link); efree(mysql); - MYSQLI_CLEAR_RESOURCE(&mysql_link); RETURN_TRUE; } /* }}} */ @@ -470,8 +585,8 @@ PHP_FUNCTION(mysqli_close) Commit outstanding actions and close transaction */ PHP_FUNCTION(mysqli_commit) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -489,8 +604,8 @@ PHP_FUNCTION(mysqli_commit) PHP_FUNCTION(mysqli_data_seek) { MYSQL_RES *result; - zval *mysql_result; - long offset; + zval *mysql_result; + long offset; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) { return; @@ -498,13 +613,13 @@ PHP_FUNCTION(mysqli_data_seek) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); - if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) { + if (mysqli_result_is_unbuffered(result)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); RETURN_FALSE; } - if (offset < 0 || offset >= result->row_count) { - RETURN_FALSE; + if (offset < 0 || offset >= mysql_num_rows(result)) { + RETURN_FALSE; } mysql_data_seek(result, offset); @@ -512,12 +627,12 @@ PHP_FUNCTION(mysqli_data_seek) } /* }}} */ -/* {{{ proto void mysqli_debug(string debug) +/* {{{ proto void mysqli_debug(string debug) U */ PHP_FUNCTION(mysqli_debug) { - char *debug; - int debug_len; + char *debug; + int debug_len; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &debug, &debug_len) == FAILURE) { return; @@ -528,25 +643,20 @@ PHP_FUNCTION(mysqli_debug) } /* }}} */ + /* {{{ proto bool mysqli_dump_debug_info(object link) */ PHP_FUNCTION(mysqli_dump_debug_info) { - MY_MYSQL *mysql; - zval *mysql_link; - ulong rc; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - rc = mysql_dump_debug_info(mysql->mysql); - - if (rc) { - RETURN_FALSE; - } - RETURN_TRUE; + RETURN_BOOL(!mysql_dump_debug_info(mysql->mysql)) } /* }}} */ @@ -554,8 +664,8 @@ PHP_FUNCTION(mysqli_dump_debug_info) Returns the numerical value of the error message from previous MySQL operation */ PHP_FUNCTION(mysqli_errno) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -569,8 +679,8 @@ PHP_FUNCTION(mysqli_errno) Returns the text of the error message from previous MySQL operation */ PHP_FUNCTION(mysqli_error) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -584,16 +694,19 @@ PHP_FUNCTION(mysqli_error) Execute a prepared statement */ PHP_FUNCTION(mysqli_stmt_execute) { - MY_STMT *stmt; - zval *mysql_stmt; - unsigned int i; + MY_STMT *stmt; + zval *mysql_stmt; +#ifndef HAVE_MYSQLND + unsigned int i; +#endif if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); - - for (i = 0; i < stmt->param.var_cnt; i++) { + +#ifndef HAVE_MYSQLND + for (i = 0; i < stmt->param.var_cnt; i++) { if (stmt->param.vars[i]) { if ( !(stmt->param.is_null[i] = (stmt->param.vars[i]->type == IS_NULL)) ) { switch (stmt->stmt->params[i].buffer_type) { @@ -604,40 +717,43 @@ PHP_FUNCTION(mysqli_stmt_execute) break; case MYSQL_TYPE_DOUBLE: convert_to_double_ex(&stmt->param.vars[i]); - stmt->stmt->params[i].buffer = (char*)&Z_LVAL_PP(&stmt->param.vars[i]); + stmt->stmt->params[i].buffer = &Z_LVAL_PP(&stmt->param.vars[i]); break; case MYSQL_TYPE_LONG: convert_to_long_ex(&stmt->param.vars[i]); - stmt->stmt->params[i].buffer = (char*)&Z_LVAL_PP(&stmt->param.vars[i]); + stmt->stmt->params[i].buffer = &Z_LVAL_PP(&stmt->param.vars[i]); break; default: break; } - } + } } } +#endif + if (mysql_stmt_execute(stmt->stmt)) { MYSQLI_REPORT_STMT_ERROR(stmt->stmt); - RETURN_FALSE; + RETVAL_FALSE; + } else { + RETVAL_TRUE; } if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { - php_mysqli_report_index(stmt->query, stmt->stmt->mysql->server_status TSRMLS_CC); + php_mysqli_report_index(stmt->query, mysqli_stmt_server_status(stmt->stmt) TSRMLS_CC); } - - RETURN_TRUE; } /* }}} */ -/* {{{ proto mixed mysqli_stmt_fetch(object stmt) +#ifndef HAVE_MYSQLND +/* {{{ void mysqli_stmt_fetch_libmysql Fetch results from a prepared statement into the bound variables */ -PHP_FUNCTION(mysqli_stmt_fetch) +void mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAMETERS) { - MY_STMT *stmt; - zval *mysql_stmt; - unsigned int i; - ulong ret; - unsigned int uval; + MY_STMT *stmt; + zval *mysql_stmt; + unsigned int i; + ulong ret; + unsigned int uval; my_ulonglong llval; @@ -647,8 +763,6 @@ PHP_FUNCTION(mysqli_stmt_fetch) MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); /* reset buffers */ - - for (i = 0; i < stmt->result.var_cnt; i++) { if (stmt->result.buf[i].type == IS_STRING) { memset(stmt->result.buf[i].val, 0, stmt->result.buf[i].buflen); @@ -661,6 +775,11 @@ PHP_FUNCTION(mysqli_stmt_fetch) if (!ret) { #endif for (i = 0; i < stmt->result.var_cnt; i++) { + /* + QQ: Isn't it quite better to call zval_dtor(). What if the user has + assigned a resource, or an array to the bound variable? We are going + to leak probably. zval_dtor() will handle also Unicode/Non-unicode mode. + */ /* Even if the string is of length zero there is one byte alloced so efree() in all cases */ if (Z_TYPE_P(stmt->result.vars[i]) == IS_STRING) { efree(stmt->result.vars[i]->value.str.val); @@ -669,11 +788,11 @@ PHP_FUNCTION(mysqli_stmt_fetch) switch (stmt->result.buf[i].type) { case IS_LONG: if ((stmt->stmt->fields[i].type == MYSQL_TYPE_LONG) - && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)) + && (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)) { /* unsigned int (11) */ uval= *(unsigned int *) stmt->result.buf[i].val; - +#if SIZEOF_LONG==4 if (uval > INT_MAX) { char *tmp, *p; int j=10; @@ -681,13 +800,14 @@ PHP_FUNCTION(mysqli_stmt_fetch) p= &tmp[9]; do { *p-- = (uval % 10) + 48; - uval = uval / 10; + uval = uval / 10; } while (--j > 0); tmp[10]= '\0'; - /* unsigned int > INT_MAX is 10 digis - ALWAYS */ + /* unsigned int > INT_MAX is 10 digits - ALWAYS */ ZVAL_STRINGL(stmt->result.vars[i], tmp, 10, 0); break; } +#endif } if (stmt->stmt->fields[i].flags & UNSIGNED_FLAG) { ZVAL_LONG(stmt->result.vars[i], *(unsigned int *)stmt->result.buf[i].val); @@ -702,11 +822,12 @@ PHP_FUNCTION(mysqli_stmt_fetch) if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_LONGLONG) { my_bool uns= (stmt->stmt->fields[i].flags & UNSIGNED_FLAG)? 1:0; llval= *(my_ulonglong *) stmt->result.buf[i].val; -#if SIZEOF_LONG==8 +#if SIZEOF_LONG==8 if (uns && llval > 9223372036854775807L) { #elif SIZEOF_LONG==4 if ((uns && llval > L64(2147483647)) || - (!uns && (( L64(2147483647) < (my_longlong) llval) || (L64(-2147483648) > (my_longlong) llval)))) + (!uns && (( L64(2147483647) < (my_longlong) llval) || + (L64(-2147483648) > (my_longlong) llval)))) { #endif char tmp[22]; @@ -719,7 +840,7 @@ PHP_FUNCTION(mysqli_stmt_fetch) } else { ZVAL_LONG(stmt->result.vars[i], llval); } - } + } #if MYSQL_VERSION_ID > 50002 else if (stmt->stmt->bind[i].buffer_type == MYSQL_TYPE_BIT) { llval = *(my_ulonglong *)stmt->result.buf[i].val; @@ -728,19 +849,21 @@ PHP_FUNCTION(mysqli_stmt_fetch) #endif else { #if defined(MYSQL_DATA_TRUNCATED) && MYSQL_VERSION_ID > 50002 - if(ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) { + if (ret == MYSQL_DATA_TRUNCATED && *(stmt->stmt->bind[i].error) != 0) { /* result was truncated */ - ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val, stmt->stmt->bind[i].buffer_length, 1); + ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val, + stmt->stmt->bind[i].buffer_length, 1); } else { #else { #endif - ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val, stmt->result.buf[i].buflen, 1); + ZVAL_STRINGL(stmt->result.vars[i], stmt->result.buf[i].val, + stmt->result.buf[i].buflen, 1); } } break; default: - break; + break; } } else { ZVAL_NULL(stmt->result.vars[i]); @@ -770,14 +893,68 @@ PHP_FUNCTION(mysqli_stmt_fetch) } } /* }}} */ +#else +/* {{{ mixed mysqli_stmt_fetch_mysqlnd */ +void mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAMETERS) +{ + MY_STMT *stmt; + zval *mysql_stmt; + zend_bool fetched_anything; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { + return; + } + MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); + + if (FAIL == mysqlnd_stmt_fetch(stmt->stmt, &fetched_anything)) { + RETURN_BOOL(FALSE); + } else if (fetched_anything == TRUE) { + RETURN_BOOL(TRUE); + } else { + RETURN_NULL(); + } +} +#endif +/* }}} */ + + +/* {{{ proto mixed mysqli_stmt_fetch(object stmt) U + Fetch results from a prepared statement into the bound variables */ +PHP_FUNCTION(mysqli_stmt_fetch) +{ +#if !defined(HAVE_MYSQLND) + mysqli_stmt_fetch_libmysql(INTERNAL_FUNCTION_PARAM_PASSTHRU); +#else + mysqli_stmt_fetch_mysqlnd(INTERNAL_FUNCTION_PARAM_PASSTHRU); +#endif +} +/* }}} */ + +/* {{{ php_add_field_properties */ +static void php_add_field_properties(zval *value, MYSQL_FIELD *field TSRMLS_DC) +{ + add_property_string(value, "name",(field->name ? field->name : ""), 1); + add_property_string(value, "orgname",(field->org_name ? field->org_name : ""), 1); + add_property_string(value, "table",(field->table ? field->table : ""), 1); + add_property_string(value, "orgtable",(field->org_table ? field->org_table : ""), 1); + add_property_string(value, "def",(field->def ? field->def : ""), 1); + + add_property_long(value, "max_length", field->max_length); + add_property_long(value, "length", field->length); + add_property_long(value, "charsetnr", field->charsetnr); + add_property_long(value, "flags", field->flags); + add_property_long(value, "type", field->type); + add_property_long(value, "decimals", field->decimals); +} +/* }}} */ /* {{{ proto mixed mysqli_fetch_field (object result) Get column information from a result and return as an object */ PHP_FUNCTION(mysqli_fetch_field) { - MYSQL_RES *result; - zval *mysql_result; - MYSQL_FIELD *field; + MYSQL_RES *result; + zval *mysql_result; + MYSQL_FIELD *field; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { return; @@ -790,18 +967,7 @@ PHP_FUNCTION(mysqli_fetch_field) } object_init(return_value); - - add_property_string(return_value, "name",(field->name ? field->name : ""), 1); - add_property_string(return_value, "orgname",(field->org_name ? field->org_name : ""), 1); - add_property_string(return_value, "table",(field->table ? field->table : ""), 1); - add_property_string(return_value, "orgtable",(field->org_table ? field->org_table : ""), 1); - add_property_string(return_value, "def",(field->def ? field->def : ""), 1); - add_property_long(return_value, "max_length", field->max_length); - add_property_long(return_value, "length", field->length); - add_property_long(return_value, "charsetnr", field->charsetnr); - add_property_long(return_value, "flags", field->flags); - add_property_long(return_value, "type", field->type); - add_property_long(return_value, "decimals", field->decimals); + php_add_field_properties(return_value, field TSRMLS_CC); } /* }}} */ @@ -810,9 +976,9 @@ PHP_FUNCTION(mysqli_fetch_field) PHP_FUNCTION(mysqli_fetch_fields) { MYSQL_RES *result; - zval *mysql_result; + zval *mysql_result; MYSQL_FIELD *field; - zval *obj; + zval *obj; unsigned int i; @@ -827,22 +993,10 @@ PHP_FUNCTION(mysqli_fetch_fields) for (i = 0; i < mysql_num_fields(result); i++) { field = mysql_fetch_field_direct(result, i); - MAKE_STD_ZVAL(obj); object_init(obj); - add_property_string(obj, "name",(field->name ? field->name : ""), 1); - add_property_string(obj, "orgname",(field->org_name ? field->org_name : ""), 1); - add_property_string(obj, "table",(field->table ? field->table : ""), 1); - add_property_string(obj, "orgtable",(field->org_table ? field->org_table : ""), 1); - add_property_string(obj, "def",(field->def ? field->def : ""), 1); - add_property_long(obj, "max_length", field->max_length); - add_property_long(obj, "length", field->length); - add_property_long(obj, "charsetnr", field->charsetnr); - add_property_long(obj, "flags", field->flags); - add_property_long(obj, "type", field->type); - add_property_long(obj, "decimals", field->decimals); - + php_add_field_properties(obj, field TSRMLS_CC); add_index_zval(return_value, i, obj); } } @@ -854,8 +1008,8 @@ PHP_FUNCTION(mysqli_fetch_field_direct) { MYSQL_RES *result; zval *mysql_result; - MYSQL_FIELD *field; - long offset; + MYSQL_FIELD *field; + long offset; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &offset) == FAILURE) { return; @@ -873,18 +1027,7 @@ PHP_FUNCTION(mysqli_fetch_field_direct) } object_init(return_value); - - add_property_string(return_value, "name",(field->name ? field->name : ""), 1); - add_property_string(return_value, "orgname",(field->org_name ? field->org_name : ""), 1); - add_property_string(return_value, "table",(field->table ? field->table : ""), 1); - add_property_string(return_value, "orgtable",(field->org_table ? field->org_table : ""), 1); - add_property_string(return_value, "def",(field->def ? field->def : ""), 1); - add_property_long(return_value, "max_length", field->max_length); - add_property_long(return_value, "length", field->length); - add_property_long(return_value, "charsetnr", field->charsetnr); - add_property_long(return_value, "flags", field->flags); - add_property_long(return_value, "type", field->type); - add_property_long(return_value, "decimals", field->decimals); + php_add_field_properties(return_value, field TSRMLS_CC); } /* }}} */ @@ -896,7 +1039,7 @@ PHP_FUNCTION(mysqli_fetch_lengths) zval *mysql_result; unsigned int i; unsigned long *ret; - + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { return; } @@ -910,7 +1053,7 @@ PHP_FUNCTION(mysqli_fetch_lengths) array_init(return_value); for (i = 0; i < mysql_num_fields(result); i++) { - add_index_long(return_value, i, ret[i]); + add_index_long(return_value, i, ret[i]); } } /* }}} */ @@ -919,17 +1062,28 @@ PHP_FUNCTION(mysqli_fetch_lengths) Get a result row as an enumerated array */ PHP_FUNCTION(mysqli_fetch_row) { +#if !defined(HAVE_MYSQLND) php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, MYSQLI_NUM, 0); +#else + MYSQL_RES *result; + zval *mysql_result; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) { + return; + } + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + mysqlnd_fetch_into(result, MYSQLND_FETCH_NUM, return_value, MYSQLND_MYSQLI); +#endif } /* }}} */ /* {{{ proto int mysqli_field_count(object link) Fetch the number of fields returned by the last query for the given link */ -PHP_FUNCTION(mysqli_field_count) +PHP_FUNCTION(mysqli_field_count) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -958,7 +1112,7 @@ PHP_FUNCTION(mysqli_field_seek) php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid field offset"); RETURN_FALSE; } - + mysql_field_seek(result, fieldnr); RETURN_TRUE; } @@ -975,7 +1129,7 @@ PHP_FUNCTION(mysqli_field_tell) return; } MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); - + RETURN_LONG(mysql_field_tell(result)); } /* }}} */ @@ -992,12 +1146,12 @@ PHP_FUNCTION(mysqli_free_result) } MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); - mysql_free_result(result); - MYSQLI_CLEAR_RESOURCE(&mysql_result); + mysqli_free_result(result, FALSE); + MYSQLI_CLEAR_RESOURCE(&mysql_result); } /* }}} */ -/* {{{ proto string mysqli_get_client_info(void) +/* {{{ proto string mysqli_get_client_info(void) Get MySQL client info */ PHP_FUNCTION(mysqli_get_client_info) { @@ -1005,7 +1159,7 @@ PHP_FUNCTION(mysqli_get_client_info) } /* }}} */ -/* {{{ proto int mysqli_get_client_version(void) +/* {{{ proto int mysqli_get_client_version(void) Get MySQL client info */ PHP_FUNCTION(mysqli_get_client_version) { @@ -1018,7 +1172,7 @@ PHP_FUNCTION(mysqli_get_client_version) PHP_FUNCTION(mysqli_get_host_info) { MY_MYSQL *mysql; - zval *mysql_link = NULL; + zval *mysql_link = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1033,24 +1187,23 @@ PHP_FUNCTION(mysqli_get_host_info) Get MySQL protocol information */ PHP_FUNCTION(mysqli_get_proto_info) { - MY_MYSQL *mysql; - zval *mysql_link = NULL; + MY_MYSQL *mysql; + zval *mysql_link = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - RETURN_LONG(mysql_get_proto_info(mysql->mysql)); } /* }}} */ -/* {{{ proto string mysqli_get_server_info(object link) +/* {{{ proto string mysqli_get_server_info(object link) Get MySQL server info */ PHP_FUNCTION(mysqli_get_server_info) { MY_MYSQL *mysql; - zval *mysql_link = NULL; + zval *mysql_link = NULL; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1083,14 +1236,16 @@ PHP_FUNCTION(mysqli_get_server_version) PHP_FUNCTION(mysqli_info) { MY_MYSQL *mysql; - zval *mysql_link = NULL; + zval *mysql_link = NULL; + const char *info; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - RETURN_STRING((mysql->mysql->info) ? mysql->mysql->info : "", 1); + info = mysql_info(mysql->mysql); + RETURN_STRING((info) ? (char *)info : "", 1); } /* }}} */ @@ -1101,7 +1256,12 @@ PHP_FUNCTION(mysqli_init) MYSQLI_RESOURCE *mysqli_resource; MY_MYSQL *mysql = (MY_MYSQL *)ecalloc(1, sizeof(MY_MYSQL)); - if (!(mysql->mysql = mysql_init(NULL))) { +#if !defined(HAVE_MYSQLND) + if (!(mysql->mysql = mysql_init(NULL))) +#else + if (!(mysql->mysql = mysql_init(FALSE))) +#endif + { efree(mysql); RETURN_FALSE; } @@ -1123,8 +1283,8 @@ PHP_FUNCTION(mysqli_init) PHP_FUNCTION(mysqli_insert_id) { MY_MYSQL *mysql; - my_ulonglong rc; - zval *mysql_link; + my_ulonglong rc; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1139,15 +1299,20 @@ PHP_FUNCTION(mysqli_insert_id) Kill a mysql process on the server */ PHP_FUNCTION(mysqli_kill) { - MY_MYSQL *mysql; - zval *mysql_link; - long processid; + MY_MYSQL *mysql; + zval *mysql_link; + long processid; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - + + if (processid <= 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "processid should have positive value"); + RETURN_FALSE; + } + if (mysql_kill(mysql->mysql, processid)) { MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); RETURN_FALSE; @@ -1158,6 +1323,7 @@ PHP_FUNCTION(mysqli_kill) /* {{{ proto void mysqli_set_local_infile_default(object link) unsets user defined handler for load local infile command */ +#if !defined(HAVE_MYSQLND) PHP_FUNCTION(mysqli_set_local_infile_default) { MY_MYSQL *mysql; @@ -1182,7 +1348,7 @@ PHP_FUNCTION(mysqli_set_local_infile_default) PHP_FUNCTION(mysqli_set_local_infile_handler) { MY_MYSQL *mysql; - zval *mysql_link; + zval *mysql_link; char *callback_name; zval *callback_func; @@ -1197,24 +1363,29 @@ PHP_FUNCTION(mysqli_set_local_infile_handler) if (!zend_is_callable(callback_func, 0, &callback_name)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not a valid callback function %s", callback_name); efree(callback_name); - RETURN_FALSE; + RETURN_FALSE; } efree(callback_name); /* save callback function */ - ALLOC_ZVAL(mysql->li_read); - ZVAL_STRING(mysql->li_read, callback_func->value.str.val, 1); + if (!mysql->li_read) { + MAKE_STD_ZVAL(mysql->li_read); + } else { + zval_dtor(mysql->li_read); + } + ZVAL_STRINGL(mysql->li_read, Z_STRVAL_P(callback_func), Z_STRLEN_P(callback_func), 1); RETURN_TRUE; } +#endif /* }}} */ /* {{{ proto bool mysqli_more_results(object link) check if there any more query results from a multi query */ PHP_FUNCTION(mysqli_more_results) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1228,14 +1399,20 @@ PHP_FUNCTION(mysqli_more_results) /* {{{ proto bool mysqli_next_result(object link) read next result from multi_query */ PHP_FUNCTION(mysqli_next_result) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); + if (!mysql_more_results(mysql->mysql)) { + php_error_docref(NULL TSRMLS_CC, E_STRICT, "There is no next result set. " + "Please, call mysqli_more_results()/mysqli::more_results() to check " + "whether to call this function/method"); + } + RETURN_BOOL(!mysql_next_result(mysql->mysql)); } /* }}} */ @@ -1268,7 +1445,7 @@ PHP_FUNCTION(mysqli_num_rows) } MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, &mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); - if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) { + if (mysqli_result_is_unbuffered(result)) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); RETURN_LONG(0); } @@ -1281,12 +1458,12 @@ PHP_FUNCTION(mysqli_num_rows) Set options */ PHP_FUNCTION(mysqli_options) { - MY_MYSQL *mysql; - zval *mysql_link = NULL; - zval *mysql_value; - long mysql_option; - unsigned int l_value; - long ret; + MY_MYSQL *mysql; + zval *mysql_link = NULL; + zval *mysql_value; + long mysql_option; + unsigned int l_value; + long ret; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) { return; @@ -1311,7 +1488,7 @@ PHP_FUNCTION(mysqli_options) } RETURN_BOOL(!ret); -} +} /* }}} */ @@ -1319,8 +1496,8 @@ PHP_FUNCTION(mysqli_options) Ping a server connection or reconnect if there is no connection */ PHP_FUNCTION(mysqli_ping) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; long rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { @@ -1339,60 +1516,71 @@ PHP_FUNCTION(mysqli_ping) PHP_FUNCTION(mysqli_prepare) { MY_MYSQL *mysql; - MY_STMT *stmt; + MY_STMT *stmt; char *query = NULL; unsigned int query_len; zval *mysql_link; - MYSQLI_RESOURCE *mysqli_resource; + MYSQLI_RESOURCE *mysqli_resource; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os",&mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); + +#if !defined(HAVE_MYSQLND) if (mysql->mysql->status == MYSQL_STATUS_GET_RESULT) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "All data must be fetched before a new statement prepare takes place"); RETURN_FALSE; } +#endif stmt = (MY_STMT *)ecalloc(1,sizeof(MY_STMT)); if ((stmt->stmt = mysql_stmt_init(mysql->mysql))) { if (mysql_stmt_prepare(stmt->stmt, query, query_len)) { - char last_error[MYSQL_ERRMSG_SIZE]; - char sqlstate[SQLSTATE_LENGTH+1]; + /* mysql_stmt_close() clears errors, so we have to store them temporarily */ +#if !defined(HAVE_MYSQLND) + char last_error[MYSQL_ERRMSG_SIZE]; + char sqlstate[SQLSTATE_LENGTH+1]; unsigned int last_errno; - /* mysql_stmt_close clears errors, so we have to store them temporarily */ last_errno = stmt->stmt->last_errno; memcpy(last_error, stmt->stmt->last_error, MYSQL_ERRMSG_SIZE); memcpy(sqlstate, mysql->mysql->net.sqlstate, SQLSTATE_LENGTH+1); - - mysql_stmt_close(stmt->stmt); +#else + mysqlnd_error_info error_info = mysql->mysql->error_info; +#endif + mysqli_stmt_close(stmt->stmt, FALSE); stmt->stmt = NULL; /* restore error messages */ +#if !defined(HAVE_MYSQLND) mysql->mysql->net.last_errno = last_errno; memcpy(mysql->mysql->net.last_error, last_error, MYSQL_ERRMSG_SIZE); memcpy(mysql->mysql->net.sqlstate, sqlstate, SQLSTATE_LENGTH+1); +#else + mysql->mysql->error_info = error_info; +#endif } } - /* don't joing to the previous if because it won't work if mysql_stmt_prepare_fails */ + + /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */ + /* Get performance boost if reporting is switched off */ + if (stmt->stmt && query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) { + stmt->query = (char *)emalloc(query_len + 1); + memcpy(stmt->query, query, query_len); + stmt->query[query_len] = '\0'; + } + + /* don't join to the previous if because it won't work if mysql_stmt_prepare_fails */ if (!stmt->stmt) { MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); efree(stmt); RETURN_FALSE; } - mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)stmt; - /* don't initialize stmt->query with NULL, we ecalloc()-ed the memory */ - /* Get performance boost if reporting is switched off */ - if (query_len && (MyG(report_mode) & MYSQLI_REPORT_INDEX)) { - stmt->query = (char *)emalloc(query_len + 1); - memcpy(stmt->query, query, query_len); - stmt->query[query_len] = '\0'; - } /* change status */ mysqli_resource->status = MYSQLI_STATUS_VALID; @@ -1404,10 +1592,10 @@ PHP_FUNCTION(mysqli_prepare) Open a connection to a mysql server */ PHP_FUNCTION(mysqli_real_connect) { - MY_MYSQL *mysql; - char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL; - unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; - unsigned long port=0, flags=0; + MY_MYSQL *mysql; + char *hostname = NULL, *username=NULL, *passwd=NULL, *dbname=NULL, *socket=NULL; + unsigned int hostname_len = 0, username_len = 0, passwd_len = 0, dbname_len = 0, socket_len = 0; + unsigned long port=0, flags=0; zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|sssslsl", &mysql_link, mysqli_link_class_entry, @@ -1419,37 +1607,38 @@ PHP_FUNCTION(mysqli_real_connect) if (!socket_len) { socket = NULL; } - - /* TODO: safe mode handling */ - if (PG(sql_safe_mode)) { - } else { - if (!passwd) { - passwd = MyG(default_pw); - if (!username){ - username = MyG(default_user); - if (!hostname) { - hostname = MyG(default_host); - } - } - } + if (!socket) { + socket = MyG(default_socket); } + if (!passwd) { + passwd = MyG(default_pw); + passwd_len = strlen(passwd); + } + if (!username){ + username = MyG(default_user); + } + if (!hostname) { + hostname = MyG(default_host); + } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED); /* remove some insecure options */ flags &= ~CLIENT_MULTI_STATEMENTS; /* don't allow multi_queries via connect parameter */ - if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) { - flags &= ~CLIENT_LOCAL_FILES; - } - - if (!socket) { - socket = MyG(default_socket); + if (PG(open_basedir) && PG(open_basedir)[0] != '\0') { + flags ^= CLIENT_LOCAL_FILES; } - if (mysql_real_connect(mysql->mysql,hostname,username,passwd,dbname,port,socket,flags) == NULL) { +#if !defined(HAVE_MYSQLND) + if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname ,port, socket ,flags) == NULL) +#else + if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len, + port, socket, flags, MyG(mysqlnd_thd_zval_cache) TSRMLS_CC) == NULL) +#endif + { php_mysqli_set_error(mysql_errno(mysql->mysql), (char *) mysql_error(mysql->mysql) TSRMLS_CC); - php_mysqli_throw_sql_exception( mysql->mysql->net.sqlstate, mysql->mysql->net.last_errno TSRMLS_CC, - "%s", mysql->mysql->net.last_error); + php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC, + "%s", mysql_error(mysql->mysql)); /* change status */ MYSQLI_SET_STATUS(&mysql_link, MYSQLI_STATUS_INITIALIZED); @@ -1458,10 +1647,14 @@ PHP_FUNCTION(mysqli_real_connect) php_mysqli_set_error(mysql_errno(mysql->mysql), (char *)mysql_error(mysql->mysql) TSRMLS_CC); +#if !defined(HAVE_MYSQLND) mysql->mysql->reconnect = MyG(reconnect); /* set our own local_infile handler */ php_set_local_infile_handler_default(mysql); +#endif + + mysql_options(mysql->mysql, MYSQL_OPT_LOCAL_INFILE, (char *)&MyG(allow_local_infile)); /* change status */ MYSQLI_SET_STATUS(&mysql_link, MYSQLI_STATUS_VALID); @@ -1477,7 +1670,7 @@ PHP_FUNCTION(mysqli_real_query) MY_MYSQL *mysql; zval *mysql_link; char *query = NULL; - unsigned int query_len; + unsigned int query_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &query, &query_len) == FAILURE) { return; @@ -1493,7 +1686,7 @@ PHP_FUNCTION(mysqli_real_query) if (!mysql_field_count(mysql->mysql)) { if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { - php_mysqli_report_index(query, mysql->mysql->server_status TSRMLS_CC); + php_mysqli_report_index(query, mysqli_server_status(mysql->mysql) TSRMLS_CC); } } @@ -1517,7 +1710,7 @@ PHP_FUNCTION(mysqli_real_escape_string) { newstr = safe_emalloc(2, escapestr_len, 1); newstr_len = mysql_real_escape_string(mysql->mysql, newstr, escapestr, escapestr_len); newstr = erealloc(newstr, newstr_len + 1); - + RETURN_STRINGL(newstr, newstr_len, 0); } /* }}} */ @@ -1527,7 +1720,7 @@ PHP_FUNCTION(mysqli_real_escape_string) { PHP_FUNCTION(mysqli_rollback) { MY_MYSQL *mysql; - zval *mysql_link; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1546,12 +1739,11 @@ PHP_FUNCTION(mysqli_rollback) PHP_FUNCTION(mysqli_stmt_send_long_data) { MY_STMT *stmt; - zval *mysql_stmt; + zval *mysql_stmt; char *data; long param_nr; int data_len; - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) { return; } @@ -1573,8 +1765,8 @@ PHP_FUNCTION(mysqli_stmt_send_long_data) Return the number of rows affected in the last query for the given link */ PHP_FUNCTION(mysqli_stmt_affected_rows) { - MY_STMT *stmt; - zval *mysql_stmt; + MY_STMT *stmt; + zval *mysql_stmt; my_ulonglong rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { @@ -1590,21 +1782,21 @@ PHP_FUNCTION(mysqli_stmt_affected_rows) } /* }}} */ -/* {{{ proto bool mysqli_stmt_close(object stmt) +/* {{{ proto bool mysqli_stmt_close(object stmt) Close statement */ PHP_FUNCTION(mysqli_stmt_close) { - MY_STMT *stmt; - zval *mysql_stmt; + MY_STMT *stmt; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); - mysql_stmt_close(stmt->stmt); + mysqli_stmt_close(stmt->stmt, FALSE); stmt->stmt = NULL; - php_clear_stmt_bind(stmt); + php_clear_stmt_bind(stmt TSRMLS_CC); MYSQLI_CLEAR_RESOURCE(&mysql_stmt); RETURN_TRUE; } @@ -1614,9 +1806,9 @@ PHP_FUNCTION(mysqli_stmt_close) Move internal result pointer */ PHP_FUNCTION(mysqli_stmt_data_seek) { - MY_STMT *stmt; - zval *mysql_stmt; - long offset; + MY_STMT *stmt; + zval *mysql_stmt; + long offset; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) { return; @@ -1636,7 +1828,7 @@ PHP_FUNCTION(mysqli_stmt_data_seek) Return the number of result columns for the given statement */ PHP_FUNCTION(mysqli_stmt_field_count) { - MY_STMT *stmt; + MY_STMT *stmt; zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { @@ -1652,8 +1844,8 @@ PHP_FUNCTION(mysqli_stmt_field_count) Free stored result memory for the given statement handle */ PHP_FUNCTION(mysqli_stmt_free_result) { - MY_STMT *stmt; - zval *mysql_stmt; + MY_STMT *stmt; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; @@ -1669,9 +1861,9 @@ PHP_FUNCTION(mysqli_stmt_free_result) Get the ID generated from the previous INSERT operation */ PHP_FUNCTION(mysqli_stmt_insert_id) { - MY_STMT *stmt; - my_ulonglong rc; - zval *mysql_stmt; + MY_STMT *stmt; + my_ulonglong rc; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; @@ -1682,13 +1874,13 @@ PHP_FUNCTION(mysqli_stmt_insert_id) } /* }}} */ -/* {{{ proto int mysqli_stmt_param_count(object stmt) { +/* {{{ proto int mysqli_stmt_param_count(object stmt) Return the number of parameter for the given statement */ PHP_FUNCTION(mysqli_stmt_param_count) { - MY_STMT *stmt; + MY_STMT *stmt; zval *mysql_stmt; - + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; } @@ -1700,10 +1892,10 @@ PHP_FUNCTION(mysqli_stmt_param_count) /* {{{ proto bool mysqli_stmt_reset(object stmt) reset a prepared statement */ -PHP_FUNCTION(mysqli_stmt_reset) +PHP_FUNCTION(mysqli_stmt_reset) { - MY_STMT *stmt; - zval *mysql_stmt; + MY_STMT *stmt; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; @@ -1722,8 +1914,8 @@ PHP_FUNCTION(mysqli_stmt_reset) Return the number of rows in statements result set */ PHP_FUNCTION(mysqli_stmt_num_rows) { - MY_STMT *stmt; - zval *mysql_stmt; + MY_STMT *stmt; + zval *mysql_stmt; my_ulonglong rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { @@ -1737,27 +1929,25 @@ PHP_FUNCTION(mysqli_stmt_num_rows) } /* }}} */ -/* {{{ proto string mysqli_select_db(object link, string dbname) +/* {{{ proto bool mysqli_select_db(object link, string dbname) Select a MySQL database */ PHP_FUNCTION(mysqli_select_db) { MY_MYSQL *mysql; - zval *mysql_link; - char *dbname; - int dbname_len; - + zval *mysql_link; + char *dbname; + int dbname_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Os", &mysql_link, mysqli_link_class_entry, &dbname, &dbname_len) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - - if (!mysql_select_db(mysql->mysql, dbname)) { - RETURN_TRUE; + + if (mysql_select_db(mysql->mysql, dbname)) { + MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); + RETURN_FALSE; } - - MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); - RETURN_FALSE; + RETURN_TRUE; } /* }}} */ @@ -1765,8 +1955,8 @@ PHP_FUNCTION(mysqli_select_db) Returns the SQLSTATE error from previous MySQL operation */ PHP_FUNCTION(mysqli_sqlstate) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1776,21 +1966,22 @@ PHP_FUNCTION(mysqli_sqlstate) } /* }}} */ -/* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher]) +/* {{{ proto bool mysqli_ssl_set(object link ,string key ,string cert ,string ca ,string capath ,string cipher]) U */ +#if !defined(HAVE_MYSQLND) PHP_FUNCTION(mysqli_ssl_set) { MY_MYSQL *mysql; - zval *mysql_link; - char *ssl_parm[5]; + zval *mysql_link; + char *ssl_parm[5]; int ssl_parm_len[5], i; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Osssss", &mysql_link, mysqli_link_class_entry, &ssl_parm[0], &ssl_parm_len[0], &ssl_parm[1], &ssl_parm_len[1], &ssl_parm[2], &ssl_parm_len[2], &ssl_parm[3], &ssl_parm_len[3], &ssl_parm[4], &ssl_parm_len[4]) == FAILURE) { return; } - MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_INITIALIZED); + MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - for (i=0; i < 5; i++) { + for (i = 0; i < 5; i++) { if (!ssl_parm_len[i]) { ssl_parm[i] = NULL; } @@ -1800,25 +1991,37 @@ PHP_FUNCTION(mysqli_ssl_set) RETURN_TRUE; } +#endif /* }}} */ /* {{{ proto mixed mysqli_stat(object link) Get current system status */ PHP_FUNCTION(mysqli_stat) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; char *stat; +#if defined(HAVE_MYSQLND) + uint stat_len; +#endif if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL *, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); - if ((stat = (char *)mysql_stat(mysql->mysql))) { +#if !defined(HAVE_MYSQLND) + if ((stat = (char *)mysql_stat(mysql->mysql))) + { RETURN_STRING(stat, 1); +#else + if (mysqlnd_stat(mysql->mysql, &stat, &stat_len) == PASS) + { + RETURN_STRINGL(stat, stat_len, 0); +#endif + } else { + RETURN_FALSE; } - RETURN_FALSE; } /* }}} */ @@ -1828,16 +2031,23 @@ PHP_FUNCTION(mysqli_stat) PHP_FUNCTION(mysqli_stmt_attr_set) { MY_STMT *stmt; - zval *mysql_stmt; - ulong mode; + zval *mysql_stmt; + long mode_in; + ulong mode; ulong attr; int rc; - if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode) == FAILURE) { + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); + if (mode_in < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "mode should be non-negative, %ld passed", mode_in); + RETURN_FALSE; + } + + mode = mode_in; if ((rc = mysql_stmt_attr_set(stmt->stmt, attr, (void *)&mode))) { RETURN_FALSE; } @@ -1850,8 +2060,8 @@ PHP_FUNCTION(mysqli_stmt_attr_set) PHP_FUNCTION(mysqli_stmt_attr_get) { MY_STMT *stmt; - zval *mysql_stmt; -#if MYSQL_VERSION_ID > 50099 + zval *mysql_stmt; +#if !defined(HAVE_MYSQLND) && MYSQL_VERSION_ID > 50099 my_bool value; #else ulong value = 0; @@ -1876,7 +2086,7 @@ PHP_FUNCTION(mysqli_stmt_attr_get) PHP_FUNCTION(mysqli_stmt_errno) { MY_STMT *stmt; - zval *mysql_stmt; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; @@ -1909,9 +2119,9 @@ PHP_FUNCTION(mysqli_stmt_error) PHP_FUNCTION(mysqli_stmt_init) { MY_MYSQL *mysql; - MY_STMT *stmt; + MY_STMT *stmt; zval *mysql_link; - MYSQLI_RESOURCE *mysqli_resource; + MYSQLI_RESOURCE *mysqli_resource; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O",&mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -1961,9 +2171,9 @@ PHP_FUNCTION(mysqli_stmt_prepare) return result set from statement */ PHP_FUNCTION(mysqli_stmt_result_metadata) { - MY_STMT *stmt; + MY_STMT *stmt; MYSQL_RES *result; - zval *mysql_stmt; + zval *mysql_stmt; MYSQLI_RESOURCE *mysqli_resource; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { @@ -1979,7 +2189,7 @@ PHP_FUNCTION(mysqli_stmt_result_metadata) mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)result; mysqli_resource->status = MYSQLI_STATUS_VALID; - MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); + MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); } /* }}} */ @@ -1987,32 +2197,37 @@ PHP_FUNCTION(mysqli_stmt_result_metadata) */ PHP_FUNCTION(mysqli_stmt_store_result) { - MY_STMT *stmt; - zval *mysql_stmt; - int i=0; + MY_STMT *stmt; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); - /* - If the user wants to store the data and we have BLOBs/TEXTs we try to allocate - not the maximal length of the type (which is 16MB even for LONGBLOB) but - the maximal length of the field in the result set. If he/she has quite big - BLOB/TEXT columns after calling store_result() the memory usage of PHP will - double - but this is a known problem of the simple MySQL API ;) - */ - for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) { - if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB || - stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB || - stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB)) - { - my_bool tmp=1; - mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp); - break; +#if !defined(HAVE_MYSQLND) + { + /* + If the user wants to store the data and we have BLOBs/TEXTs we try to allocate + not the maximal length of the type (which is 16MB even for LONGBLOB) but + the maximal length of the field in the result set. If he/she has quite big + BLOB/TEXT columns after calling store_result() the memory usage of PHP will + double - but this is a known problem of the simple MySQL API ;) + */ + int i = 0; + + for (i = mysql_stmt_field_count(stmt->stmt) - 1; i >=0; --i) { + if (stmt->stmt->fields && (stmt->stmt->fields[i].type == MYSQL_TYPE_BLOB || + stmt->stmt->fields[i].type == MYSQL_TYPE_MEDIUM_BLOB || + stmt->stmt->fields[i].type == MYSQL_TYPE_LONG_BLOB)) + { + my_bool tmp=1; + mysql_stmt_attr_set(stmt->stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &tmp); + break; + } } } +#endif if (mysql_stmt_store_result(stmt->stmt)){ MYSQLI_REPORT_STMT_ERROR(stmt->stmt); @@ -2024,16 +2239,16 @@ PHP_FUNCTION(mysqli_stmt_store_result) /* {{{ proto string mysqli_stmt_sqlstate(object stmt) */ -PHP_FUNCTION(mysqli_stmt_sqlstate) +PHP_FUNCTION(mysqli_stmt_sqlstate) { - MY_STMT *stmt; - zval *mysql_stmt; + MY_STMT *stmt; + zval *mysql_stmt; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_stmt, mysqli_stmt_class_entry) == FAILURE) { return; } MYSQLI_FETCH_RESOURCE(stmt, MY_STMT *, &mysql_stmt, "mysqli_stmt", MYSQLI_STATUS_VALID); - + RETURN_STRING((char *)mysql_stmt_sqlstate(stmt->stmt),1); } /* }}} */ @@ -2042,9 +2257,9 @@ PHP_FUNCTION(mysqli_stmt_sqlstate) Buffer result set on client */ PHP_FUNCTION(mysqli_store_result) { - MY_MYSQL *mysql; - MYSQL_RES *result; - zval *mysql_link; + MY_MYSQL *mysql; + MYSQL_RES *result; + zval *mysql_link; MYSQLI_RESOURCE *mysqli_resource; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { @@ -2057,22 +2272,23 @@ PHP_FUNCTION(mysqli_store_result) RETURN_FALSE; } if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { - php_mysqli_report_index("from previous query", mysql->mysql->server_status TSRMLS_CC); + php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql) TSRMLS_CC); } mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)result; mysqli_resource->status = MYSQLI_STATUS_VALID; - MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); + MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); } /* }}} */ + /* {{{ proto int mysqli_thread_id(object link) Return the current thread ID */ PHP_FUNCTION(mysqli_thread_id) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -2089,17 +2305,16 @@ PHP_FUNCTION(mysqli_thread_safe) { RETURN_BOOL(mysql_thread_safe()); } - /* }}} */ /* {{{ proto mixed mysqli_use_result(object link) Directly retrieve query results - do not buffer results on client side */ PHP_FUNCTION(mysqli_use_result) { - MY_MYSQL *mysql; - MYSQL_RES *result; - zval *mysql_link; - MYSQLI_RESOURCE *mysqli_resource; + MY_MYSQL *mysql; + MYSQL_RES *result; + zval *mysql_link; + MYSQLI_RESOURCE *mysqli_resource; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; @@ -2112,12 +2327,12 @@ PHP_FUNCTION(mysqli_use_result) } if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { - php_mysqli_report_index("from previous query", mysql->mysql->server_status TSRMLS_CC); + php_mysqli_report_index("from previous query", mysqli_server_status(mysql->mysql) TSRMLS_CC); } mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); mysqli_resource->ptr = (void *)result; mysqli_resource->status = MYSQLI_STATUS_VALID; - MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); + MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); } /* }}} */ @@ -2125,8 +2340,8 @@ PHP_FUNCTION(mysqli_use_result) Return number of warnings from the last query for the given link */ PHP_FUNCTION(mysqli_warning_count) { - MY_MYSQL *mysql; - zval *mysql_link; + MY_MYSQL *mysql; + zval *mysql_link; if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { return; |
