From e131a7ef9a2fd317d55eeba512aabccd9c9c5ce9 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Fri, 3 Jul 2020 13:43:29 +0200 Subject: [PATCH 01/12] Warning to Error promotion in MySQLi extension --- ext/mysqli/mysqli.c | 14 ++- ext/mysqli/mysqli.stub.php | 8 +- ext/mysqli/mysqli_api.c | 94 ++++++++++++++----- ext/mysqli/mysqli_arginfo.h | 8 +- ext/mysqli/mysqli_nonapi.c | 77 ++++++++------- ext/mysqli/tests/bug74595.phpt | 2 +- ext/mysqli/tests/connect.inc | 2 +- .../tests/mysqli_begin_transaction.phpt | 13 +-- ext/mysqli/tests/mysqli_data_seek.phpt | 9 +- ext/mysqli/tests/mysqli_data_seek_oo.phpt | 8 +- ext/mysqli/tests/mysqli_fetch_all.phpt | 17 ++-- ext/mysqli/tests/mysqli_fetch_all_oo.phpt | 19 ++-- .../tests/mysqli_fetch_field_direct.phpt | 9 +- .../tests/mysqli_fetch_field_direct_oo.phpt | 11 ++- ext/mysqli/tests/mysqli_field_seek.phpt | 9 +- ext/mysqli/tests/mysqli_field_tell.phpt | 10 +- ext/mysqli/tests/mysqli_kill.phpt | 28 ++++-- ext/mysqli/tests/mysqli_poll.phpt | 21 +++-- ext/mysqli/tests/mysqli_query.phpt | 19 ++-- .../tests/mysqli_release_savepoint.phpt | 11 ++- ext/mysqli/tests/mysqli_report.phpt | 18 ++-- .../tests/mysqli_result_invalid_mode.phpt | 22 ++--- ext/mysqli/tests/mysqli_savepoint.phpt | 11 ++- ext/mysqli/tests/mysqli_stmt_attr_get.phpt | 14 ++- ext/mysqli/tests/mysqli_stmt_attr_set.phpt | 45 ++++----- ext/mysqli/tests/mysqli_stmt_bind_param.phpt | 92 +++++++++++++----- ext/mysqli/tests/mysqli_stmt_bind_result.phpt | 27 ++++-- ext/mysqli/tests/mysqli_stmt_data_seek.phpt | 10 +- .../mysqli_stmt_execute_stored_proc_out.phpt | 8 +- ext/mysqli/tests/mysqli_stmt_field_count.phpt | 13 ++- .../mysqli_stmt_get_result_metadata.phpt | 18 +++- .../tests/mysqli_stmt_get_result_seek.phpt | 34 ++++--- .../tests/mysqli_stmt_send_long_data.phpt | 12 ++- .../tests/mysqli_store_result_copy.phpt | 14 ++- 34 files changed, 459 insertions(+), 268 deletions(-) diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index b2f85bc147df0..bed3619870d05 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -384,8 +384,7 @@ static int mysqli_object_has_property(zend_object *object, zend_string *name, in } break; } - default: - php_error_docref(NULL, E_WARNING, "Invalid value for has_set_exists"); + EMPTY_SWITCH_DEFAULT_CASE(); } } else { ret = zend_std_has_property(object, name, has_set_exists, cache_slot); @@ -1025,6 +1024,11 @@ PHP_METHOD(mysqli_result, __construct) RETURN_THROWS(); } + if (resmode != MYSQLI_STORE_RESULT && resmode != MYSQLI_USE_RESULT) { + zend_argument_value_error(2, "must be MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT"); + RETURN_THROWS(); + } + MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); switch (resmode) { @@ -1034,8 +1038,7 @@ PHP_METHOD(mysqli_result, __construct) case MYSQLI_USE_RESULT: result = mysql_use_result(mysql->mysql); break; - default: - php_error_docref(NULL, E_WARNING, "Invalid value for resultmode"); + EMPTY_SWITCH_DEFAULT_CASE(); } if (!result) { @@ -1052,7 +1055,7 @@ PHP_METHOD(mysqli_result, __construct) PHP_METHOD(mysqli_result, getIterator) { if (zend_parse_parameters_none() == FAILURE) { - return; + RETURN_THROWS(); } zend_create_internal_iterator_zval(return_value, ZEND_THIS); @@ -1130,6 +1133,7 @@ void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend } /* }}} */ +/* TODO Split this up */ /* {{{ php_mysqli_fetch_into_hash */ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags, int into_object) { diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 940f3c4fcc749..2b2653cf7e564 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -164,7 +164,7 @@ public function prepare(string $query) {} * @return mysqli_result|bool * @alias mysqli_query */ - public function query(string $query, int $resultmode = MYSQLI_STORE_RESULT) {} + public function query(string $query, int $result_mode = MYSQLI_STORE_RESULT) {} /** * @return bool @@ -421,7 +421,7 @@ public function bind_result(mixed &...$vars) {} public function close() {} /** - * @return bool|null + * @return void * @alias mysqli_stmt_data_seek */ public function data_seek(int $offset) {} @@ -641,7 +641,7 @@ function mysqli_prepare(mysqli $mysqli_link, string $query): mysqli_stmt|false { function mysqli_report(int $flags): bool {} -function mysqli_query(mysqli $mysqli_link, string $query, int $resultmode = MYSQLI_STORE_RESULT): mysqli_result|bool {} +function mysqli_query(mysqli $mysqli_link, string $query, int $result_mode = MYSQLI_STORE_RESULT): mysqli_result|bool {} function mysqli_real_connect( mysqli $mysqli_link, @@ -672,7 +672,7 @@ function mysqli_set_charset(mysqli $mysqli_link, string $charset): bool {} function mysqli_stmt_affected_rows(mysqli_stmt $mysql_stmt): int|string {} -function mysqli_stmt_attr_get(mysqli_stmt $mysql_stmt, int $attr): int|false {} +function mysqli_stmt_attr_get(mysqli_stmt $mysql_stmt, int $attr): int {} function mysqli_stmt_attr_set(mysqli_stmt $mysql_stmt, int $attr, int $mode_in): bool {} diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 3f89e838fd894..3e01d4fe4cbcd 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -31,6 +31,8 @@ #include "mysqli_priv.h" #include "ext/mysqlnd/mysql_float_to_double.h" +#define ERROR_ARG_POS(arg_num) (getThis() ? (arg_num-1) : (arg_num)) + #ifndef MYSQLI_USE_MYSQLND /* {{{ mysqli_tx_cor_options_to_string */ @@ -324,19 +326,19 @@ PHP_FUNCTION(mysqli_stmt_bind_param) MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); if (!types_len) { - php_error_docref(NULL, E_WARNING, "Invalid type or no types specified"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "cannot be empty"); + RETURN_THROWS(); } if (types_len != (size_t) argc) { /* number of bind variables doesn't match number of elements in type definition string */ - php_error_docref(NULL, E_WARNING, "Number of elements in type definition string doesn't match number of bind variables"); - RETURN_FALSE; + zend_argument_count_error("Number of elements in type definition string doesn't match number of bind variables"); + RETURN_THROWS(); } if (types_len != mysql_stmt_param_count(stmt->stmt)) { - php_error_docref(NULL, E_WARNING, "Number of variables doesn't match number of parameters in prepared statement"); - RETURN_FALSE; + zend_argument_count_error("Number of variables doesn't match number of parameters in prepared statement"); + RETURN_THROWS(); } RETVAL_BOOL(!mysqli_stmt_bind_param_do_bind(stmt, argc, args, types, getThis() ? 1 : 2)); @@ -557,8 +559,8 @@ PHP_FUNCTION(mysqli_stmt_bind_result) MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); if ((uint32_t)argc != mysql_stmt_field_count(stmt->stmt)) { - php_error_docref(NULL, E_WARNING, "Number of bind variables doesn't match number of fields in prepared statement"); - RETURN_FALSE; + zend_argument_count_error("Number of bind variables doesn't match number of fields in prepared statement"); + RETURN_THROWS(); } rc = mysqli_stmt_bind_result_do_bind(stmt, args, argc); @@ -729,14 +731,21 @@ PHP_FUNCTION(mysqli_data_seek) RETURN_THROWS(); } + if (offset < 0) { + zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0"); + RETURN_THROWS(); + } + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered(result)) { + // TODO Promoto to Exception? php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); RETURN_FALSE; } - if (offset < 0 || (uint64_t)offset >= mysql_num_rows(result)) { + if ((uint64_t)offset >= mysql_num_rows(result)) { + // TODO Warning/Exception? RETURN_FALSE; } @@ -1181,9 +1190,15 @@ PHP_FUNCTION(mysqli_fetch_field_direct) RETURN_THROWS(); } + if (offset < 0) { + zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0"); + RETURN_THROWS(); + } + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); - if (offset < 0 || offset >= (zend_long) mysql_num_fields(result)) { + if (offset >= (zend_long) mysql_num_fields(result)) { + // TODO ValueError? php_error_docref(NULL, E_WARNING, "Field offset is invalid for resultset"); RETURN_FALSE; } @@ -1215,6 +1230,7 @@ PHP_FUNCTION(mysqli_fetch_lengths) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); + // TODO Warning? if (!(ret = mysql_fetch_lengths(result))) { RETURN_FALSE; } @@ -1260,9 +1276,16 @@ PHP_FUNCTION(mysqli_field_seek) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_result, mysqli_result_class_entry, &fieldnr) == FAILURE) { RETURN_THROWS(); } + + if (fieldnr < 0) { + zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0"); + RETURN_THROWS(); + } + MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); - if (fieldnr < 0 || (uint32_t)fieldnr >= mysql_num_fields(result)) { + if ((uint32_t)fieldnr >= mysql_num_fields(result)) { + // TODO ValueError? php_error_docref(NULL, E_WARNING, "Invalid field offset"); RETURN_FALSE; } @@ -1499,13 +1522,14 @@ PHP_FUNCTION(mysqli_kill) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_link, mysqli_link_class_entry, &processid) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); if (processid <= 0) { - php_error_docref(NULL, E_WARNING, "processid should have positive value"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than 0"); + RETURN_THROWS(); } + MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); + if (mysql_kill(mysql->mysql, processid)) { MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); RETURN_FALSE; @@ -1601,6 +1625,7 @@ PHP_FUNCTION(mysqli_num_rows) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) { + // TODO Exception? php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); RETURN_LONG(0); } @@ -1922,12 +1947,14 @@ PHP_FUNCTION(mysqli_stmt_send_long_data) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ols", &mysql_stmt, mysqli_stmt_class_entry, ¶m_nr, &data, &data_len) == FAILURE) { RETURN_THROWS(); } + MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); if (param_nr < 0) { - php_error_docref(NULL, E_WARNING, "Invalid parameter number"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0"); + RETURN_THROWS(); } + if (mysql_stmt_send_long_data(stmt->stmt, param_nr, data, data_len)) { RETURN_FALSE; } @@ -1984,9 +2011,10 @@ PHP_FUNCTION(mysqli_stmt_data_seek) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &offset) == FAILURE) { RETURN_THROWS(); } + if (offset < 0) { - php_error_docref(NULL, E_WARNING, "Offset must be positive"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "must be greater than or equal to 0"); + RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); @@ -2225,13 +2253,15 @@ PHP_FUNCTION(mysqli_stmt_attr_set) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oll", &mysql_stmt, mysqli_stmt_class_entry, &attr, &mode_in) == FAILURE) { RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); + /* TODO Improve the mode to depend on the ATTR */ if (mode_in < 0) { - php_error_docref(NULL, E_WARNING, "Mode should be non-negative, " ZEND_LONG_FMT " passed", mode_in); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(3), "must be greater than or equal to 0"); + RETURN_THROWS(); } + MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); + switch (attr) { #if MYSQL_VERSION_ID >= 50107 case STMT_ATTR_UPDATE_MAX_LENGTH: @@ -2244,6 +2274,7 @@ PHP_FUNCTION(mysqli_stmt_attr_set) mode_p = &mode; break; } + #ifndef MYSQLI_USE_MYSQLND if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) { #else @@ -2262,17 +2293,32 @@ PHP_FUNCTION(mysqli_stmt_attr_get) zval *mysql_stmt; unsigned long value = 0; zend_long attr; - int rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) { RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); - if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) { - RETURN_FALSE; + switch (attr) { +#if MYSQL_VERSION_ID >= 50107 + case STMT_ATTR_UPDATE_MAX_LENGTH: +#endif + case STMT_ATTR_CURSOR_TYPE: + case STMT_ATTR_PREFETCH_ROWS: + break; + default: + zend_argument_value_error(ERROR_ARG_POS(2), "must be one of " +#if MYSQL_VERSION_ID >= 50107 + "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, " +#endif + "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE"); + RETURN_THROWS(); } + /* Success corresponds to 0 return value and a non-zero value + * should only happen if the attr/option is unknown */ + ZEND_ASSERT(mysql_stmt_attr_get(stmt->stmt, attr, &value) == 0); + #if MYSQL_VERSION_ID >= 50107 if (attr == STMT_ATTR_UPDATE_MAX_LENGTH) value = *((my_bool *)&value); diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 7d7c69e943919..8189ad5adc730 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a8626c7c42e4d117b08df7f42a7523f60f357b82 */ + * Stub hash: 473cceef8ade1758128ddb348ec3c90216d12b3f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql_link, mysqli, 0) @@ -233,7 +233,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_mysqli_query, 0, 2, mysqli_result, MAY_BE_BOOL) ZEND_ARG_OBJ_INFO(0, mysqli_link, mysqli, 0) ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resultmode, IS_LONG, 0, "MYSQLI_STORE_RESULT") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, result_mode, IS_LONG, 0, "MYSQLI_STORE_RESULT") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_real_connect, 0, 1, _IS_BOOL, 0) @@ -285,7 +285,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_stmt_affected_rows, 0, 1, ZEND_ARG_OBJ_INFO(0, mysql_stmt, mysqli_stmt, 0) ZEND_END_ARG_INFO() -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_stmt_attr_get, 0, 2, MAY_BE_LONG|MAY_BE_FALSE) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_attr_get, 0, 2, IS_LONG, 0) ZEND_ARG_OBJ_INFO(0, mysql_stmt, mysqli_stmt, 0) ZEND_ARG_TYPE_INFO(0, attr, IS_LONG, 0) ZEND_END_ARG_INFO() @@ -502,7 +502,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_query, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, query, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resultmode, IS_LONG, 0, "MYSQLI_STORE_RESULT") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, result_mode, IS_LONG, 0, "MYSQLI_STORE_RESULT") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_real_connect, 0, 0, 0) diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 9b675bb526326..52a28def27f94 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -28,6 +28,7 @@ #include "zend_smart_str.h" #include "php_mysqli_structs.h" #include "mysqli_priv.h" +#define ERROR_ARG_POS(arg_num) (getThis() ? (arg_num-1) : (arg_num)) #define SAFE_STR(a) ((a)?a:"") @@ -435,9 +436,9 @@ PHP_FUNCTION(mysqli_fetch_all) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (!mode || (mode & ~MYSQLND_FETCH_BOTH)) { - php_error_docref(NULL, E_WARNING, "Mode can be only MYSQLI_FETCH_NUM, " - "MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_FETCH_NUM, " + "MYSQLI_FETCH_ASSOC, or MYSQLI_FETCH_BOTH"); + RETURN_THROWS(); } mysqlnd_fetch_all(result, mode, return_value); @@ -631,16 +632,23 @@ PHP_FUNCTION(mysqli_query) } if (!query_len) { - php_error_docref(NULL, E_WARNING, "Empty query"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "cannot be empty"); + RETURN_THROWS(); } -#ifdef MYSQLI_USE_MYSQLND - if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) != MYSQLI_STORE_RESULT) { -#else - if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) { -#endif - php_error_docref(NULL, E_WARNING, "Invalid value for resultmode"); - RETURN_FALSE; + if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && + MYSQLI_STORE_RESULT != + #ifdef MYSQLI_USE_MYSQLND + (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) + #else + (resultmode & ~MYSQLI_ASYNC) + #endif + ) { + zend_argument_value_error(ERROR_ARG_POS(3), "must be one of " + #ifdef MYSQLI_USE_MYSQLND + "MYSQLI_ASYNC," + #endif + "MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT"); + RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); @@ -722,7 +730,8 @@ static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_ar i++; if (Z_TYPE_P(elem) != IS_OBJECT || !instanceof_function(Z_OBJCE_P(elem), mysqli_link_class_entry)) { - php_error_docref(NULL, E_WARNING, "Parameter %d not a mysqli object", i); + zend_argument_type_error(i, "must be an instance of mysqli, %s given", zend_zval_type_name(elem)); + return FAILURE; } else { MY_MYSQL *mysql; MYSQLI_RESOURCE *my_res; @@ -831,11 +840,16 @@ PHP_FUNCTION(mysqli_poll) if (zend_parse_parameters(ZEND_NUM_ARGS(), "a!a!al|l", &r_array, &e_array, &dont_poll_array, &sec, &usec) == FAILURE) { RETURN_THROWS(); } - if (sec < 0 || usec < 0) { - php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec"); - RETURN_FALSE; + if (sec < 0) { + zend_argument_value_error(4, "must be greater than or equal to 0"); + RETURN_THROWS(); + } + if (usec < 0) { + zend_argument_value_error(5, "must be greater than or equal to 0"); + RETURN_THROWS(); } + // TODO Error promotion if (!r_array && !e_array) { php_error_docref(NULL, E_WARNING, "No stream arrays were passed"); RETURN_FALSE; @@ -1152,22 +1166,21 @@ PHP_FUNCTION(mysqli_begin_transaction) zend_long flags = TRANS_START_NO_OPT; char * name = NULL; size_t name_len = -1; - zend_bool err = FALSE; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O|ls!", &mysql_link, mysqli_link_class_entry, &flags, &name, &name_len) == FAILURE) { RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); if (flags < 0) { - php_error_docref(NULL, E_WARNING, "Invalid value for parameter flags (" ZEND_LONG_FMT ")", flags); - err = TRUE; + zend_argument_value_error(ERROR_ARG_POS(2), "must be MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT" + /* TODO Only MySQL 5.6 and later */ + ", MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE" + ); + RETURN_THROWS(); } if (!name_len) { - php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty"); - err = TRUE; - } - if (TRUE == err) { - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(3), "cannot be empty"); + RETURN_THROWS(); } #ifndef MYSQLI_USE_MYSQLND @@ -1203,15 +1216,15 @@ PHP_FUNCTION(mysqli_savepoint) MY_MYSQL *mysql; zval *mysql_link; char * name = NULL; - size_t name_len = -1; + size_t name_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &name, &name_len) == FAILURE) { RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); - if (!name || !name_len) { - php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty"); - RETURN_FALSE; + if (name_len == 0) { + zend_argument_value_error(ERROR_ARG_POS(2), "cannot be empty"); + RETURN_THROWS(); } #ifndef MYSQLI_USE_MYSQLND @@ -1231,15 +1244,15 @@ PHP_FUNCTION(mysqli_release_savepoint) MY_MYSQL *mysql; zval *mysql_link; char * name = NULL; - size_t name_len = -1; + size_t name_len; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &mysql_link, mysqli_link_class_entry, &name, &name_len) == FAILURE) { RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); - if (!name || !name_len) { - php_error_docref(NULL, E_WARNING, "Savepoint name cannot be empty"); - RETURN_FALSE; + if (name_len == 0) { + zend_argument_value_error(ERROR_ARG_POS(2), "cannot be empty"); + RETURN_THROWS(); } #ifndef MYSQLI_USE_MYSQLND if (mysqli_savepoint_libmysql(mysql->mysql, name, TRUE)) { diff --git a/ext/mysqli/tests/bug74595.phpt b/ext/mysqli/tests/bug74595.phpt index 9d017eaa82b51..0fdebc7027f9e 100644 --- a/ext/mysqli/tests/bug74595.phpt +++ b/ext/mysqli/tests/bug74595.phpt @@ -20,6 +20,6 @@ array(2) { [1]=> object(ReflectionParameter)#%d (1) { ["name"]=> - string(10) "resultmode" + string(11) "result_mode" } } diff --git a/ext/mysqli/tests/connect.inc b/ext/mysqli/tests/connect.inc index 43bb3c4153f83..6bf393a2de665 100644 --- a/ext/mysqli/tests/connect.inc +++ b/ext/mysqli/tests/connect.inc @@ -8,7 +8,7 @@ $driver = new mysqli_driver; - $host = getenv("MYSQL_TEST_HOST") ?: "localhost"; + $host = getenv("MYSQL_TEST_HOST") ?: "127.0.0.1"; $port = getenv("MYSQL_TEST_PORT") ?: 3306; $user = getenv("MYSQL_TEST_USER") ?: "root"; $passwd = getenv("MYSQL_TEST_PASSWD") ?: ""; diff --git a/ext/mysqli/tests/mysqli_begin_transaction.phpt b/ext/mysqli/tests/mysqli_begin_transaction.phpt index bed9b1bf61321..115f9a60f8141 100644 --- a/ext/mysqli/tests/mysqli_begin_transaction.phpt +++ b/ext/mysqli/tests/mysqli_begin_transaction.phpt @@ -76,8 +76,11 @@ if (!have_innodb($link)) } } - if (!mysqli_begin_transaction($link, -1)) { - printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); + try { + mysqli_begin_transaction($link, -1); + printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; } if (mysqli_get_server_version($link) >= 50605) { @@ -96,9 +99,7 @@ if (!have_innodb($link)) ---EXPECTF-- +--EXPECT-- NULL - -Warning: mysqli_begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d -[019] [%d]%A +mysqli_begin_transaction(): Argument #2 ($flags) must be MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT, MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE done! diff --git a/ext/mysqli/tests/mysqli_data_seek.phpt b/ext/mysqli/tests/mysqli_data_seek.phpt index 53c8b8354d5b2..5a6587449b155 100644 --- a/ext/mysqli/tests/mysqli_data_seek.phpt +++ b/ext/mysqli/tests/mysqli_data_seek.phpt @@ -31,8 +31,11 @@ require_once('skipifconnectfailure.inc'); if (false !== ($tmp = mysqli_data_seek($res, 4))) printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); - if (false !== ($tmp = mysqli_data_seek($res, -1))) - printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_data_seek($res, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_free_result($res); @@ -59,6 +62,8 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECTF-- +mysqli_data_seek(): Argument #2 ($offset) must be greater than or equal to 0 + Warning: mysqli_data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_data_seek_oo.phpt b/ext/mysqli/tests/mysqli_data_seek_oo.phpt index 0d1ee8b79f6e5..55561f95032e2 100644 --- a/ext/mysqli/tests/mysqli_data_seek_oo.phpt +++ b/ext/mysqli/tests/mysqli_data_seek_oo.phpt @@ -43,8 +43,11 @@ require_once('skipifconnectfailure.inc'); if (false !== ($tmp = $res->data_seek(4))) printf("[011] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); - if (false !== ($tmp = $res->data_seek(-1))) - printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + $res->data_seek(-1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } $res->free_result(); @@ -71,6 +74,7 @@ require_once('skipifconnectfailure.inc'); ?> --EXPECTF-- mysqli_result object is already closed +mysqli_result::data_seek(): Argument #1 ($offset) must be greater than or equal to 0 Warning: mysqli_result::data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d mysqli_result object is already closed diff --git a/ext/mysqli/tests/mysqli_fetch_all.phpt b/ext/mysqli/tests/mysqli_fetch_all.phpt index 76c6b971f41a9..ab48821498e0d 100644 --- a/ext/mysqli/tests/mysqli_fetch_all.phpt +++ b/ext/mysqli/tests/mysqli_fetch_all.phpt @@ -71,12 +71,12 @@ if (!function_exists('mysqli_fetch_all')) exit(1); } - do { - $illegal_mode = mt_rand(-10000, 10000); - } while (in_array($illegal_mode, array(MYSQLI_ASSOC, MYSQLI_NUM, MYSQLI_BOTH))); - // NOTE: for BC reasons with ext/mysql, ext/mysqli accepts invalid result modes. - - mysqli_fetch_all($res, $illegal_mode); + // Illegal mode + try { + mysqli_fetch_all($res, -10); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_free_result($res); function func_mysqli_fetch_all($link, $engine, $sql_type, $sql_value, $php_value, $offset, $regexp_comparison = NULL) { @@ -315,7 +315,7 @@ if (!function_exists('mysqli_fetch_all')) ---EXPECTF-- +--EXPECT-- [005] array(2) { [0]=> @@ -443,7 +443,6 @@ array(1) { string(1) "1" } } - -Warning: mysqli_fetch_all(): Mode can be only MYSQLI_FETCH_NUM, MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH in %s on line %d +mysqli_fetch_all(): Argument #2 ($mode) must be one of MYSQLI_FETCH_NUM, MYSQLI_FETCH_ASSOC, or MYSQLI_FETCH_BOTH mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_fetch_all_oo.phpt b/ext/mysqli/tests/mysqli_fetch_all_oo.phpt index 992a61a348bc8..2b34670756583 100644 --- a/ext/mysqli/tests/mysqli_fetch_all_oo.phpt +++ b/ext/mysqli/tests/mysqli_fetch_all_oo.phpt @@ -81,14 +81,14 @@ if (!function_exists('mysqli_fetch_all')) exit(1); } - do { - $illegal_mode = mt_rand(-10000, 10000); - } while (in_array($illegal_mode, array(MYSQLI_ASSOC, MYSQLI_NUM, MYSQLI_BOTH))); - // NOTE: for BC reasons with ext/mysql, ext/mysqli accepts invalid result modes. - $tmp = $res->fetch_all($illegal_mode); - if (false !== $tmp) - printf("[019] Expecting boolean/false although, got %s/%s. [%d] %s\n", - gettype($tmp), $tmp, $mysqli->errno, $mysqli->error); + try { + $tmp = $res->fetch_all(-10); + if (false !== $tmp) + printf("[019] Expecting boolean/false although, got %s/%s. [%d] %s\n", + gettype($tmp), $tmp, $mysqli->errno, $mysqli->error); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } $res->free_result(); @@ -436,7 +436,6 @@ array(1) { string(1) "1" } } - -Warning: mysqli_result::fetch_all(): Mode can be only MYSQLI_FETCH_NUM, MYSQLI_FETCH_ASSOC or MYSQLI_FETCH_BOTH in %s on line %d +mysqli_result::fetch_all(): Argument #1 ($result_type) must be one of MYSQLI_FETCH_NUM, MYSQLI_FETCH_ASSOC, or MYSQLI_FETCH_BOTH mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_fetch_field_direct.phpt b/ext/mysqli/tests/mysqli_fetch_field_direct.phpt index 0afe6e4626af7..ad02eccfdc0bf 100644 --- a/ext/mysqli/tests/mysqli_fetch_field_direct.phpt +++ b/ext/mysqli/tests/mysqli_fetch_field_direct.phpt @@ -16,7 +16,11 @@ require_once('skipifconnectfailure.inc'); printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } - var_dump(mysqli_fetch_field_direct($res, -1)); + try { + var_dump(mysqli_fetch_field_direct($res, -1)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } var_dump(mysqli_fetch_field_direct($res, 0)); var_dump(mysqli_fetch_field_direct($res, 2)); @@ -36,8 +40,7 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECTF-- -Warning: mysqli_fetch_field_direct(): Field offset is invalid for resultset in %s on line %d -bool(false) +mysqli_fetch_field_direct(): Argument #2 ($offset) must be greater than or equal to 0 object(stdClass)#%d (13) { ["name"]=> string(2) "ID" diff --git a/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt b/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt index 33806f1c553f0..cb13f946734a5 100644 --- a/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt +++ b/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt @@ -27,7 +27,12 @@ require_once('skipifconnectfailure.inc'); printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } - var_dump($res->fetch_field_direct(-1)); + try { + var_dump($res->fetch_field_direct(-1)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } + var_dump($res->fetch_field_direct(0)); var_dump($res->fetch_field_direct(2)); @@ -48,9 +53,7 @@ require_once('skipifconnectfailure.inc'); ?> --EXPECTF-- mysqli object is not fully initialized - -Warning: mysqli_result::fetch_field_direct(): Field offset is invalid for resultset in %s on line %d -bool(false) +mysqli_result::fetch_field_direct(): Argument #1 ($field_nr) must be greater than or equal to 0 object(stdClass)#%d (13) { ["name"]=> string(2) "ID" diff --git a/ext/mysqli/tests/mysqli_field_seek.phpt b/ext/mysqli/tests/mysqli_field_seek.phpt index 9eb9f0315b071..bcc1e29526c54 100644 --- a/ext/mysqli/tests/mysqli_field_seek.phpt +++ b/ext/mysqli/tests/mysqli_field_seek.phpt @@ -69,7 +69,11 @@ require_once('skipifconnectfailure.inc'); printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); } - var_dump(mysqli_field_seek($res, -1)); + try { + var_dump(mysqli_field_seek($res, -1)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } var_dump(mysqli_fetch_field($res)); var_dump(mysqli_field_seek($res, 0)); var_dump(mysqli_fetch_field($res)); @@ -115,8 +119,7 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECTF-- -Warning: mysqli_field_seek(): Invalid field offset in %s on line %d -bool(false) +mysqli_field_seek(): Argument #2 ($field_nr) must be greater than or equal to 0 object(stdClass)#%d (13) { ["name"]=> string(2) "id" diff --git a/ext/mysqli/tests/mysqli_field_tell.phpt b/ext/mysqli/tests/mysqli_field_tell.phpt index bf169003aa7e0..e8c344ec956ff 100644 --- a/ext/mysqli/tests/mysqli_field_tell.phpt +++ b/ext/mysqli/tests/mysqli_field_tell.phpt @@ -24,7 +24,11 @@ require_once('skipifconnectfailure.inc'); var_dump(mysqli_field_seek($res, 2)); var_dump(mysqli_field_tell($res)); - var_dump(mysqli_field_seek($res, -1)); + try { + var_dump(mysqli_field_seek($res, -1)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } var_dump(mysqli_field_tell($res)); var_dump(mysqli_field_seek($res, 0)); @@ -85,9 +89,7 @@ int(1) Warning: mysqli_field_seek(): Invalid field offset in %s on line %d bool(false) int(1) - -Warning: mysqli_field_seek(): Invalid field offset in %s on line %d -bool(false) +mysqli_field_seek(): Argument #2 ($field_nr) must be greater than or equal to 0 int(1) bool(true) int(0) diff --git a/ext/mysqli/tests/mysqli_kill.phpt b/ext/mysqli/tests/mysqli_kill.phpt index 943e213a81a36..e4be618fc7fa6 100644 --- a/ext/mysqli/tests/mysqli_kill.phpt +++ b/ext/mysqli/tests/mysqli_kill.phpt @@ -13,8 +13,11 @@ require_once('skipifconnectfailure.inc'); require('table.inc'); // Zend will cast the NULL to 0 - if (!is_bool($tmp = mysqli_kill($link, null))) - printf("[003] Expecting boolean/any, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_kill($link, null); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (!$thread_id = mysqli_thread_id($link)) printf("[004] Cannot determine thread id, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); @@ -46,7 +49,11 @@ require_once('skipifconnectfailure.inc'); if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[010] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); - mysqli_kill($link, -1); + try { + mysqli_kill($link, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if ((!$res = mysqli_query($link, "SELECT id FROM test LIMIT 1")) || (!$tmp = mysqli_fetch_assoc($res))) { printf("[011] Connection should not be gone, [%d] %s\n", mysqli_errno($link), mysqli_error($link)); @@ -58,7 +65,12 @@ require_once('skipifconnectfailure.inc'); if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[012] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); - mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db); mysqli_kill($link, -1); + mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db); + try { + mysqli_kill($link, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_close($link); @@ -69,7 +81,7 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECTF-- -Warning: mysqli_kill(): processid should have positive value in %s on line %d +mysqli_kill(): Argument #2 ($connection_id) must be greater than 0 string(%d) "%s" bool(false) object(mysqli)#%d (%d) { @@ -120,12 +132,10 @@ object(mysqli)#%d (%d) { ["warning_count"]=> int(0) } - -Warning: mysqli_kill(): processid should have positive value in %s on line %d +mysqli_kill(): Argument #2 ($connection_id) must be greater than 0 array(1) { ["id"]=> string(1) "1" } - -Warning: mysqli_kill(): processid should have positive value in %s on line %d +mysqli_kill(): Argument #2 ($connection_id) must be greater than 0 done! diff --git a/ext/mysqli/tests/mysqli_poll.phpt b/ext/mysqli/tests/mysqli_poll.phpt index 97b1a7e61ad77..cc3cc36b2f8fb 100644 --- a/ext/mysqli/tests/mysqli_poll.phpt +++ b/ext/mysqli/tests/mysqli_poll.phpt @@ -30,12 +30,16 @@ if (!$IS_MYSQLND) printf("[009] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true)); $read = $error = $reject = array($link); - if (false !== ($tmp = (mysqli_poll($read, $error, $reject, -1, 1)))) - printf("[010] Expecting false got %s/%s\n", gettype($tmp), var_export($tmp, true)); - - $read = $error = $reject = array($link); - if (false !== ($tmp = (mysqli_poll($read, $error, $reject, 0, -1)))) - printf("[011] Expecting false got %s/%s\n", gettype($tmp), var_export($tmp, true)); + try { + mysqli_poll($read, $error, $reject, -1, 1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + mysqli_poll($read, $error, $reject, 0, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } function poll_async($offset, $link, $links, $errors, $reject, $exp_ready, $use_oo_syntax) { @@ -111,9 +115,8 @@ if (!$IS_MYSQLND) print "done!"; ?> --EXPECTF-- -Warning: mysqli_poll(): Negative values passed for sec and/or usec in %s on line %d - -Warning: mysqli_poll(): Negative values passed for sec and/or usec in %s on line %d +mysqli_poll(): Argument #4 ($sec) must be greater than or equal to 0 +mysqli_poll(): Argument #5 ($usec) must be greater than or equal to 0 [012 + 6] Rejecting thread %d: 0/ [013 + 6] Rejecting thread %d: 0/ [014 + 6] Rejecting thread %d: 0/ diff --git a/ext/mysqli/tests/mysqli_query.phpt b/ext/mysqli/tests/mysqli_query.phpt index ba159cf9852ed..9b8d8e9f9b10c 100644 --- a/ext/mysqli/tests/mysqli_query.phpt +++ b/ext/mysqli/tests/mysqli_query.phpt @@ -12,8 +12,11 @@ require_once('skipifconnectfailure.inc'); require('table.inc'); - if (false !== ($tmp = @mysqli_query($link, ''))) - printf("[002a] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_query($link, ''); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (false !== ($tmp = mysqli_query($link, 'THIS IS NOT SQL'))) printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); @@ -82,11 +85,11 @@ require_once('skipifconnectfailure.inc'); printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); mysqli_free_result($res); - if (false !== ($res = @mysqli_query($link, "SELECT id FROM test ORDER BY id", 1234))) - printf("[013] Invalid mode should return false got %s/%s, [%d] %s\n", - gettype($res), (is_object($res)) ? 'object' : $res, - mysqli_errno($link), mysqli_error($link)); - + try { + mysqli_query($link, "SELECT id FROM test ORDER BY id", 1234); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_close($link); @@ -113,6 +116,7 @@ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) mysqli_close($link); ?> --EXPECT-- +mysqli_query(): Argument #2 ($query) cannot be empty array(1) { ["valid"]=> string(30) "this is sql but with semicolon" @@ -122,5 +126,6 @@ array(1) { string(1) "a" } string(1) "a" +mysqli_query(): Argument #3 ($result_mode) must be one of MYSQLI_ASYNC,MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT mysqli object is already closed done! diff --git a/ext/mysqli/tests/mysqli_release_savepoint.phpt b/ext/mysqli/tests/mysqli_release_savepoint.phpt index 92f85c8b7576c..fa46366e7cac8 100644 --- a/ext/mysqli/tests/mysqli_release_savepoint.phpt +++ b/ext/mysqli/tests/mysqli_release_savepoint.phpt @@ -23,8 +23,11 @@ if (!have_innodb($link)) printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket); - if (false !== ($tmp = mysqli_release_savepoint($link, ''))) - printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_release_savepoint($link, ''); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); @@ -61,8 +64,8 @@ if (!have_innodb($link)) ---EXPECTF-- -Warning: mysqli_release_savepoint(): Savepoint name cannot be empty in %s on line %d +--EXPECT-- +mysqli_release_savepoint(): Argument #2 ($name) cannot be empty array(1) { ["id"]=> string(1) "1" diff --git a/ext/mysqli/tests/mysqli_report.phpt b/ext/mysqli/tests/mysqli_report.phpt index 17baea0f66f95..6f5733513ca3b 100644 --- a/ext/mysqli/tests/mysqli_report.phpt +++ b/ext/mysqli/tests/mysqli_report.phpt @@ -37,7 +37,11 @@ require_once('skipifconnectfailure.inc'); mysqli_multi_query($link, "BAR; FOO;"); mysqli_query($link, "FOO"); - mysqli_kill($link, -1); + try { + mysqli_kill($link, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } // mysqli_ping() cannot be tested, because one would need to cause an error inside the C function to test it mysqli_prepare($link, "FOO"); @@ -53,7 +57,11 @@ require_once('skipifconnectfailure.inc'); mysqli_multi_query($link, "BAR; FOO;"); mysqli_query($link, "FOO"); - mysqli_kill($link, -1); + try { + mysqli_kill($link, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_prepare($link, "FOO"); mysqli_real_query($link, "FOO"); mysqli_select_db($link, "Oh lord, let this be an unknown database name"); @@ -280,14 +288,12 @@ require_once('skipifconnectfailure.inc'); Warning: mysqli_multi_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'BAR; FOO' at line 1 in %s on line %d Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d - -Warning: mysqli_kill(): processid should have positive value in %s on line %d +mysqli_kill(): Argument #2 ($connection_id) must be greater than 0 Warning: mysqli_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d Warning: mysqli_real_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d - -Warning: mysqli_kill(): processid should have positive value in %s on line %d +mysqli_kill(): Argument #2 ($connection_id) must be greater than 0 Warning: mysqli_stmt_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'FOO' at line 1 in %s on line %d [013] Access denied for user '%s'@'%s' (using password: YES) diff --git a/ext/mysqli/tests/mysqli_result_invalid_mode.phpt b/ext/mysqli/tests/mysqli_result_invalid_mode.phpt index 9f902920dbf44..65c692c222445 100644 --- a/ext/mysqli/tests/mysqli_result_invalid_mode.phpt +++ b/ext/mysqli/tests/mysqli_result_invalid_mode.phpt @@ -12,19 +12,19 @@ require_once('skipifconnectfailure.inc'); require('table.inc'); $valid = array(MYSQLI_STORE_RESULT, MYSQLI_USE_RESULT); - do { - $mode = mt_rand(-1000, 1000); - } while (in_array($mode, $valid)); - - if (!is_object($res = new mysqli_result($link, $mode))) - printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); - - print "done!"; + $invalidModes = [-1, 152]; + foreach ($invalidModes as $mode) { + try { + new mysqli_result($link, $mode); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } + } ?> --CLEAN-- ---EXPECTF-- -Warning: mysqli_result::__construct(): Invalid value for resultmode in %s on line %d -done! +--EXPECT-- +mysqli_result::__construct(): Argument #2 ($result_mode) must be MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT +mysqli_result::__construct(): Argument #2 ($result_mode) must be MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT diff --git a/ext/mysqli/tests/mysqli_savepoint.phpt b/ext/mysqli/tests/mysqli_savepoint.phpt index 524d21e5c3eb4..10016256671d3 100644 --- a/ext/mysqli/tests/mysqli_savepoint.phpt +++ b/ext/mysqli/tests/mysqli_savepoint.phpt @@ -21,8 +21,11 @@ if (!have_innodb($link)) printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", $host, $user, $db, $port, $socket); - if (false !== ($tmp = mysqli_savepoint($link, ''))) - printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_savepoint($link, ''); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); @@ -50,6 +53,6 @@ if (!have_innodb($link)) ---EXPECTF-- -Warning: mysqli_savepoint(): Savepoint name cannot be empty in %s on line %d +--EXPECT-- +mysqli_savepoint(): Argument #2 ($name) cannot be empty done! diff --git a/ext/mysqli/tests/mysqli_stmt_attr_get.phpt b/ext/mysqli/tests/mysqli_stmt_attr_get.phpt index 0844a6c8acc7c..6179155e777b1 100644 --- a/ext/mysqli/tests/mysqli_stmt_attr_get.phpt +++ b/ext/mysqli/tests/mysqli_stmt_attr_get.phpt @@ -19,20 +19,17 @@ require_once('skipifconnectfailure.inc'); if ($IS_MYSQLND && mysqli_get_client_version() > 50007) $valid_attr["prefetch_rows"] = MYSQLI_STMT_ATTR_PREFETCH_ROWS; - do { - $invalid_attr = mt_rand(0, 10000); - } while (in_array($invalid_attr, $valid_attr)); - $stmt = mysqli_stmt_init($link); mysqli_stmt_prepare($stmt, 'SELECT * FROM test'); try { - mysqli_stmt_attr_get($stmt, $invalid_attr); - } catch (Error $exception) { - echo $exception->getMessage() . "\n"; + mysqli_stmt_attr_get($stmt, -100); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; } foreach ($valid_attr as $k => $attr) { + /* This can't happen anymore as it only returns int */ if (false === ($tmp = mysqli_stmt_attr_get($stmt, $attr))) { printf("[006] Expecting any type, but not boolean/false, got %s/%s for attribute %s/%s\n", gettype($tmp), $tmp, $k, $attr); @@ -44,7 +41,7 @@ require_once('skipifconnectfailure.inc'); foreach ($valid_attr as $k => $attr) { try { mysqli_stmt_attr_get($stmt, $attr); - } catch (Error $exception) { + } catch (Throwable $exception) { echo $exception->getMessage() . "\n"; } } @@ -57,6 +54,7 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECT-- +mysqli_stmt_attr_get(): Argument #2 ($attr) must be one of MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE mysqli_stmt object is already closed mysqli_stmt object is already closed mysqli_stmt object is already closed diff --git a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt index 4fad53cba2fbe..cc7c5184711c3 100644 --- a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt +++ b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt @@ -28,8 +28,8 @@ require_once("connect.inc"); $stmt = mysqli_stmt_init($link); try { mysqli_stmt_attr_set($stmt, 0, 0); - } catch (Error $exception) { - echo $exception->getMessage() . "\n"; + } catch (\Throwable $e) { + echo get_class($e) . ': ' . $e->getMessage() . PHP_EOL; } $stmt->prepare("SELECT * FROM test"); @@ -40,18 +40,22 @@ require_once("connect.inc"); if (in_array($i, $valid_attr)) continue; $invalid_attr = $i; - if (false !== ($tmp = @mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) { - printf("[006a] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp); - } + try { + if (false !== ($tmp = mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) { + printf("[006a] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp); + } + } catch (\ValueError $e) {/* Suppress because RANDOM */} } for ($i = 0; $i < 2; $i++) { do { $invalid_attr = mt_rand(-1 * (min(4294967296, PHP_INT_MAX) + 1), min(4294967296, PHP_INT_MAX)); } while (in_array($invalid_attr, $valid_attr)); - if (false !== ($tmp = @mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) { - printf("[006b] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp); - } + try { + if (false !== ($tmp = mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) { + printf("[006b] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp); + } + } catch (\ValueError $e) {/* Suppress because RANDOM */} } $stmt->close(); @@ -122,21 +126,19 @@ require_once("connect.inc"); if (mysqli_get_client_version() > 50003) { - $cursor_types = array( - MYSQLI_CURSOR_TYPE_NO_CURSOR, - MYSQLI_CURSOR_TYPE_READ_ONLY, - MYSQLI_CURSOR_TYPE_FOR_UPDATE, - MYSQLI_CURSOR_TYPE_SCROLLABLE - ); - do { - $invalid_cursor_type = mt_rand(-1000, 1000); - } while (in_array($invalid_cursor_type, $cursor_types)); - $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT id, label FROM test"); - if (false !== ($tmp = @$stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, $invalid_cursor_type))) - printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, -100); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, 200); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE))) printf("[011] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); @@ -262,5 +264,6 @@ require_once("connect.inc"); require_once("clean_table.inc"); ?> --EXPECT-- -mysqli_stmt object is not fully initialized +Error: mysqli_stmt object is not fully initialized +mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be greater than or equal to 0 done! diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt index aba40decf4525..6c66c5a069edc 100644 --- a/ext/mysqli/tests/mysqli_stmt_bind_param.phpt +++ b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt @@ -32,35 +32,77 @@ require_once('skipifconnectfailure.inc'); libmysql gives a less descriptive error message but mysqlnd, we did not unify the error messages but ignore this slight difference silently */ - if (!false === ($tmp = @mysqli_stmt_bind_param($stmt, " ", $tmp))) - printf("[003d] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, " ", $tmp))) + printf("[003d] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } - if (!false === ($tmp = @mysqli_stmt_bind_param($stmt, "", $id, $label))) - printf("[003a] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "", $id, $label))) + printf("[003a] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } /* TODO: somehwhat undocumented syntax! */ $param = array($id); - if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param))) - printf("[003b] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param))) + printf("[003b] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } $param = array($id, $label, $id); - if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param))) - printf("[003c] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, " ", $tmp))) + printf("[003d] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param))) + printf("[003c] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } - if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id))) - printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id))) + printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } - if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id, $label))) - printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id, $label))) + printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } - if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "aa", $id, $label))) - printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "aa", $id, $label))) + printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } - if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "ia", $id, $label))) - printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "ia", $id, $label))) + printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } - if (!true === ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label))) - printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + if (!true === ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label))) + printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (function_exists("memory_get_usage")) { $mem = memory_get_usage(); @@ -374,13 +416,13 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECTF-- -Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d - -Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d - -Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in %s on line %d - -Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d +Number of variables doesn't match number of parameters in prepared statement +mysqli_stmt_bind_param(): Argument #2 ($types) cannot be empty +Number of elements in type definition string doesn't match number of bind variables +Number of variables doesn't match number of parameters in prepared statement +Number of elements in type definition string doesn't match number of bind variables +Number of variables doesn't match number of parameters in prepared statement +Number of elements in type definition string doesn't match number of bind variables Warning: mysqli_stmt_bind_param(): Undefined fieldtype a (parameter 3) in %s on line %d diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result.phpt index c1dddca4f294b..f9556ad0f6380 100644 --- a/ext/mysqli/tests/mysqli_stmt_bind_result.phpt +++ b/ext/mysqli/tests/mysqli_stmt_bind_result.phpt @@ -31,14 +31,20 @@ require_once('skipifconnectfailure.inc'); if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1")) printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); - if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id))) - printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_stmt_bind_result($stmt, $id); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; + } if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label))) printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); - if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label, $foo))) - printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_stmt_bind_result($stmt, $id, $label, $foo); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . PHP_EOL; + } if (!mysqli_stmt_execute($stmt)) printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); @@ -290,8 +296,11 @@ require_once('skipifconnectfailure.inc'); printf("[3001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); $id = null; - if (false !== @mysqli_stmt_bind_result($stmt, $id)) - printf("[3002] Bind result should not be allowed"); + try { + mysqli_stmt_bind_result($stmt, $id); + } catch (\ArgumentCountError $e) { + $e->getMessage() . \PHP_EOL; + } mysqli_stmt_close($stmt); @@ -304,10 +313,8 @@ require_once('skipifconnectfailure.inc'); ?> --EXPECTF-- mysqli_stmt object is not fully initialized - -Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d - -Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d +Number of bind variables doesn't match number of fields in prepared statement +Number of bind variables doesn't match number of fields in prepared statement int(1) %s(1) "a" done! diff --git a/ext/mysqli/tests/mysqli_stmt_data_seek.phpt b/ext/mysqli/tests/mysqli_stmt_data_seek.phpt index 72d807512f730..5594600747792 100644 --- a/ext/mysqli/tests/mysqli_stmt_data_seek.phpt +++ b/ext/mysqli/tests/mysqli_stmt_data_seek.phpt @@ -59,8 +59,11 @@ require_once('skipifconnectfailure.inc'); var_dump($id); - if (false !== ($tmp = mysqli_stmt_data_seek($stmt, -1))) - printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); + try { + mysqli_stmt_data_seek($stmt, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (mysqli_stmt_fetch($stmt)) printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); @@ -87,8 +90,7 @@ mysqli_stmt object is not fully initialized int(3) int(1) int(1) - -Warning: mysqli_stmt_data_seek(): Offset must be positive in %s on line %d +mysqli_stmt_data_seek(): Argument #2 ($offset) must be greater than or equal to 0 int(1) mysqli_stmt object is already closed done! diff --git a/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt index c65330ebc951e..7cbbc74988e9b 100644 --- a/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt +++ b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc_out.phpt @@ -44,8 +44,12 @@ if ($IS_MYSQLND) { printf("[008] More results: %s\n", (mysqli_more_results($link) ? "yes" : "no")); printf("[009] Next results: %s\n", (mysqli_next_result($link) ? "yes" : "no")); - if (!mysqli_stmt_bind_result($stmt, $ver_out) || !mysqli_stmt_fetch($stmt)) - printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); + try { + if (!mysqli_stmt_bind_result($stmt, $ver_out) || !mysqli_stmt_fetch($stmt)) + printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } if ("myversion" !== $ver_out) printf("[011] Results seem wrong got '%s'\n", $ver_out); diff --git a/ext/mysqli/tests/mysqli_stmt_field_count.phpt b/ext/mysqli/tests/mysqli_stmt_field_count.phpt index 51afb04e1b6f9..75afa990011d0 100644 --- a/ext/mysqli/tests/mysqli_stmt_field_count.phpt +++ b/ext/mysqli/tests/mysqli_stmt_field_count.phpt @@ -51,8 +51,12 @@ require_once('skipifconnectfailure.inc'); printf("[013] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp); $label = null; - if (mysqli_stmt_bind_param($stmt, "s", $label)) - printf("[014] expected error - got ok\n"); + try { + if (mysqli_stmt_bind_param($stmt, "s", $label)) + printf("[014] expected error - got ok\n"); + } catch (\ArgumentCountError $e) { + echo $e->getMessage() . \PHP_EOL; + } while (mysqli_stmt_fetch($stmt)) if (1 !== ($tmp = mysqli_stmt_field_count($stmt))) printf("[015] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp); @@ -91,11 +95,10 @@ require_once('skipifconnectfailure.inc'); ---EXPECTF-- +--EXPECT-- mysqli_stmt object is not fully initialized mysqli_stmt object is not fully initialized - -Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in %s on line %d +Number of variables doesn't match number of parameters in prepared statement mysqli_stmt object is already closed mysqli_stmt object is already closed done! diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt index cb95ed896afbe..9e6ddec044b4f 100644 --- a/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt +++ b/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt @@ -182,11 +182,19 @@ if (!function_exists('mysqli_stmt_get_result')) printf("[032] Expecting %s/%s got %s/%s\n", gettype($pos), $pos, gettype($tmp), $tmp); } else { - - if (false !== @mysqli_field_seek($res, $pos)) - printf("[033] field_seek(%d) did not fail\n", $pos); - if (false !== @mysqli_field_seek($res_meta, $pos)) - printf("[034] field_seek(%d) did not fail\n", $pos); + try { + $tmp = @mysqli_field_seek($res, $pos); + if ($pos >= $num && $tmp !== false) { + printf("[033] field_seek(%d) did not fail\n", $pos); + } + } catch (ValueError $e) { /* Suppress output because pos is RANDOM */} + + try { + $tmp = @mysqli_field_seek($res_meta, $pos); + if ($pos >= $num && $tmp !== false) { + printf("[034] field_seek(%d) did not fail\n", $pos); + } + } catch (ValueError $e) { /* Suppress output because pos is RANDOM */} } } diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt index 68dad8b281731..cf9e634cc9e31 100644 --- a/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt +++ b/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt @@ -61,8 +61,11 @@ if (!function_exists('mysqli_stmt_get_result')) } } - if (false !== ($tmp = $res->data_seek(-1))) - printf("[011] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp); + try { + $res->data_seek(-1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (false !== ($tmp = $res->data_seek($res->num_rows + 1))) printf("[012] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp); @@ -70,18 +73,20 @@ if (!function_exists('mysqli_stmt_get_result')) for ($i = 0; $i < 100; $i++) { /* intentionally out of range! */ $pos = mt_rand(-1, 4); - $tmp = mysqli_data_seek($res, $pos); - if (($pos >= 0 && $pos < 3)) { - if (true !== $tmp) - printf("[015] Expecting boolan/true got %s/%s\n", gettype($tmp), $tmp); - $row = $res->fetch_array(MYSQLI_NUM); - if ($row[0] !== $pos + 1) - printf("[016] Expecting id = %d for pos %d got %s/%s\n", - $pos + 1, $pos, gettype($row[0]), $row[0]); - } else { - if (false !== $tmp) - printf("[014] Expecting boolan/false got %s/%s\n", gettype($tmp), $tmp); - } + try { + $tmp = @mysqli_data_seek($res, $pos); + if (($pos >= 0 && $pos < 3)) { + if (true !== $tmp) + printf("[015] Expecting boolan/true got %s/%s\n", gettype($tmp), $tmp); + $row = $res->fetch_array(MYSQLI_NUM); + if ($row[0] !== $pos + 1) + printf("[016] Expecting id = %d for pos %d got %s/%s\n", + $pos + 1, $pos, gettype($row[0]), $row[0]); + } else { + if (false !== $tmp) + printf("[014] Expecting boolan/false got %s/%s\n", gettype($tmp), $tmp); + } + } catch (\ValueError $e) { /* Suppress because RANDOM */} } mysqli_stmt_close($stmt); @@ -127,6 +132,7 @@ if (!function_exists('mysqli_stmt_get_result')) require_once("clean_table.inc"); ?> --EXPECT-- +mysqli_result::data_seek(): Argument #1 ($offset) must be greater than or equal to 0 mysqli_result object is already closed mysqli_result object is already closed mysqli_result object is already closed diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt index 00afa5513df79..705f19e8c2178 100644 --- a/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt +++ b/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt @@ -64,9 +64,11 @@ require_once('skipifconnectfailure.inc'); */ assert(strlen($blob) <= $max_allowed_packet); - if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, -1, $blob))) - printf("[012] Expecting boolean/false, got %s/%s. [%d] %s\n", - gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); + try { + $tmp = mysqli_stmt_send_long_data($stmt, -1, $blob); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, 999, $blob))) printf("[014] Expecting boolean/false, got %s/%s. [%d] %s\n", @@ -106,6 +108,6 @@ require_once('skipifconnectfailure.inc'); ---EXPECTF-- -Warning: mysqli_stmt_send_long_data(): Invalid parameter number in %s on line %d +--EXPECT-- +mysqli_stmt_send_long_data(): Argument #2 ($param_nr) must be greater than or equal to 0 done! diff --git a/ext/mysqli/tests/mysqli_store_result_copy.phpt b/ext/mysqli/tests/mysqli_store_result_copy.phpt index 136e2c5d4d9a5..c431a05a60c26 100644 --- a/ext/mysqli/tests/mysqli_store_result_copy.phpt +++ b/ext/mysqli/tests/mysqli_store_result_copy.phpt @@ -63,12 +63,16 @@ mysqlnd.fetch_data_copy=0 $no_result = 0; for ($i = 0; $i < 1000; $i++) { $idx = mt_rand(-100, 100); - if (true === @mysqli_data_seek($res, $idx)) { - $row = $res->fetch_assoc(); - if (!isset($row['id']) || !isset($row['label'])) { - printf("[010] Brute force seek %d returned %d\n", $idx, var_export($row, true)); + try { + if (true === @mysqli_data_seek($res, $idx)) { + $row = $res->fetch_assoc(); + if (!isset($row['id']) || !isset($row['label'])) { + printf("[010] Brute force seek %d returned %d\n", $idx, var_export($row, true)); + } + } else { + $no_result++; } - } else { + } catch (\ValueError $e) { $no_result++; } } From cb4598cd896f9910dd68c9c0beffc207e0a5bca7 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sat, 4 Jul 2020 01:39:02 +0200 Subject: [PATCH 02/12] Improve errors for mysqli_stmt_attr_set() --- ext/mysqli/mysqli_api.c | 47 ++++++++++++++---- ext/mysqli/tests/mysqli_stmt_attr_set.phpt | 55 ++++++++++------------ 2 files changed, 62 insertions(+), 40 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 3e01d4fe4cbcd..73f183ed5b0b5 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -2243,9 +2243,6 @@ PHP_FUNCTION(mysqli_stmt_attr_set) MY_STMT *stmt; zval *mysql_stmt; zend_long mode_in; -#if MYSQL_VERSION_ID >= 50107 - my_bool mode_b; -#endif unsigned long mode; zend_long attr; void *mode_p; @@ -2254,27 +2251,57 @@ PHP_FUNCTION(mysqli_stmt_attr_set) RETURN_THROWS(); } - /* TODO Improve the mode to depend on the ATTR */ - if (mode_in < 0) { - zend_argument_value_error(ERROR_ARG_POS(3), "must be greater than or equal to 0"); - RETURN_THROWS(); - } - MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); switch (attr) { #if MYSQL_VERSION_ID >= 50107 case STMT_ATTR_UPDATE_MAX_LENGTH: + { + my_bool mode_b; + if (mode_in != 0 && mode_in != 1) { + zend_argument_value_error(ERROR_ARG_POS(3), "must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH"); + RETURN_THROWS(); + } mode_b = (my_bool) mode_in; mode_p = &mode_b; break; + } #endif - default: + case STMT_ATTR_CURSOR_TYPE: { + switch (mode_in) { + case CURSOR_TYPE_NO_CURSOR: + case CURSOR_TYPE_READ_ONLY: + case CURSOR_TYPE_FOR_UPDATE: + case CURSOR_TYPE_SCROLLABLE: + break; + default: + zend_argument_value_error(ERROR_ARG_POS(3), "must be one of MYSQLI_CURSOR_TYPE_NO_CURSOR, " + "MYSQLI_CURSOR_TYPE_READ_ONLY, MYSQLI_CURSOR_TYPE_FOR_UPDATE, or MYSQLI_CURSOR_TYPE_SCROLLABLE " + "for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE"); + RETURN_THROWS(); + } mode = mode_in; mode_p = &mode; break; } + case STMT_ATTR_PREFETCH_ROWS: + if (mode_in < 1) { + zend_argument_value_error(ERROR_ARG_POS(3), "must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS"); + RETURN_THROWS(); + } + mode = mode_in; + mode_p = &mode; + break; + default: + zend_argument_value_error(ERROR_ARG_POS(2), "must be one of " +#if MYSQL_VERSION_ID >= 50107 + "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, " +#endif + "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE"); + RETURN_THROWS(); + } +// TODO Can unify this? #ifndef MYSQLI_USE_MYSQLND if (mysql_stmt_attr_set(stmt->stmt, attr, mode_p)) { #else diff --git a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt index cc7c5184711c3..c9250b0de06c6 100644 --- a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt +++ b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt @@ -33,29 +33,11 @@ require_once("connect.inc"); } $stmt->prepare("SELECT * FROM test"); - - mt_srand(microtime(true)); - - for ($i = -100; $i < 1000; $i++) { - if (in_array($i, $valid_attr)) - continue; - $invalid_attr = $i; - try { - if (false !== ($tmp = mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) { - printf("[006a] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp); - } - } catch (\ValueError $e) {/* Suppress because RANDOM */} - } - - for ($i = 0; $i < 2; $i++) { - do { - $invalid_attr = mt_rand(-1 * (min(4294967296, PHP_INT_MAX) + 1), min(4294967296, PHP_INT_MAX)); - } while (in_array($invalid_attr, $valid_attr)); - try { - if (false !== ($tmp = mysqli_stmt_attr_set($stmt, $invalid_attr, 0))) { - printf("[006b] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp); - } - } catch (\ValueError $e) {/* Suppress because RANDOM */} + // Invalid Attribute (2nd argument) + try { + mysqli_stmt_attr_set($stmt, -1, 0); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; } $stmt->close(); @@ -117,6 +99,13 @@ require_once("connect.inc"); if ($meta->max_length !== 0) printf("[009] max_length should not be set (= 0), got %s for field %s\n", $meta->max_length, $meta->name); } + + // Invalid mode for MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH + try { + $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } $res->close(); $stmt->close(); @@ -129,13 +118,9 @@ require_once("connect.inc"); $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT id, label FROM test"); + // Invalid cursor type try { - $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, -100); - } catch (\ValueError $e) { - echo $e->getMessage() . \PHP_EOL; - } - try { - $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, 200); + $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, -1); } catch (\ValueError $e) { echo $e->getMessage() . \PHP_EOL; } @@ -211,6 +196,13 @@ require_once("connect.inc"); $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT id, label FROM test"); + // Invalid prefetch value + try { + $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 0); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } + if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 1))) printf("[020] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); $stmt->execute(); @@ -265,5 +257,8 @@ require_once("connect.inc"); ?> --EXPECT-- Error: mysqli_stmt object is not fully initialized -mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be greater than or equal to 0 +mysqli_stmt_attr_set(): Argument #2 ($attr) must be one of MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE +mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH +mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be one of MYSQLI_CURSOR_TYPE_NO_CURSOR, MYSQLI_CURSOR_TYPE_READ_ONLY, MYSQLI_CURSOR_TYPE_FOR_UPDATE, or MYSQLI_CURSOR_TYPE_SCROLLABLE for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE +mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS done! From da7904d41c8981e608e6f4e32a3c13df4a3cc0f2 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 7 Jul 2020 19:34:01 +0200 Subject: [PATCH 03/12] Debug output --- ext/mysqli/tests/mysqli_stmt_attr_set.phpt | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt index c9250b0de06c6..870960e602f9a 100644 --- a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt +++ b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt @@ -39,13 +39,17 @@ require_once("connect.inc"); } catch (\ValueError $e) { echo $e->getMessage() . \PHP_EOL; } + // Invalid mode for MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH + try { + $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, -1); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } $stmt->close(); // // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH // - - // expecting max_length not to be set and be 0 in all cases $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT label FROM test"); @@ -65,7 +69,7 @@ require_once("connect.inc"); // expecting max_length to _be_ set $stmt = mysqli_stmt_init($link); $stmt->prepare("SELECT label FROM test"); - $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1); + var_dump($stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1)); $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH); if ($res !== 1) printf("[007.1] max_length should be 1, got %s\n", $res); @@ -99,13 +103,6 @@ require_once("connect.inc"); if ($meta->max_length !== 0) printf("[009] max_length should not be set (= 0), got %s for field %s\n", $meta->max_length, $meta->name); } - - // Invalid mode for MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH - try { - $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, -1); - } catch (\ValueError $e) { - echo $e->getMessage() . \PHP_EOL; - } $res->close(); $stmt->close(); @@ -259,6 +256,7 @@ require_once("connect.inc"); Error: mysqli_stmt object is not fully initialized mysqli_stmt_attr_set(): Argument #2 ($attr) must be one of MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH +bool(true) mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be one of MYSQLI_CURSOR_TYPE_NO_CURSOR, MYSQLI_CURSOR_TYPE_READ_ONLY, MYSQLI_CURSOR_TYPE_FOR_UPDATE, or MYSQLI_CURSOR_TYPE_SCROLLABLE for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE mysqli_stmt::attr_set(): Argument #2 ($mode_in) must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS done! From 9f6aeadb27da13bdf2c4f00d6903e2c3f26c1333 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 3 Aug 2020 02:48:27 +0100 Subject: [PATCH 04/12] Nit from review --- ext/mysqli/mysqli_nonapi.c | 2 +- ext/mysqli/tests/mysqli_begin_transaction.phpt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 52a28def27f94..5880c288d8d19 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -1172,7 +1172,7 @@ PHP_FUNCTION(mysqli_begin_transaction) } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); if (flags < 0) { - zend_argument_value_error(ERROR_ARG_POS(2), "must be MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT" + zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT" /* TODO Only MySQL 5.6 and later */ ", MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE" ); diff --git a/ext/mysqli/tests/mysqli_begin_transaction.phpt b/ext/mysqli/tests/mysqli_begin_transaction.phpt index 115f9a60f8141..3d314aee26044 100644 --- a/ext/mysqli/tests/mysqli_begin_transaction.phpt +++ b/ext/mysqli/tests/mysqli_begin_transaction.phpt @@ -101,5 +101,5 @@ if (!have_innodb($link)) ?> --EXPECT-- NULL -mysqli_begin_transaction(): Argument #2 ($flags) must be MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT, MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE +mysqli_begin_transaction(): Argument #2 ($flags) must be one of MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT, MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE done! From 48be020352bd3adbab0689ff42ea556502ff82c0 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 23 Aug 2020 22:49:12 +0200 Subject: [PATCH 05/12] Fix stubs param name --- ext/mysqli/mysqli.stub.php | 2 +- ext/mysqli/mysqli_arginfo.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 2b2653cf7e564..6b2c70341432a 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -301,7 +301,7 @@ public function refresh(int $options) {} class mysqli_result implements IteratorAggregate { - public function __construct(object $mysqli_link, int $resmode = MYSQLI_STORE_RESULT) {} + public function __construct(object $mysqli_link, int $result_mode = MYSQLI_STORE_RESULT) {} /** * @return void diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 8189ad5adc730..dab786bc458a3 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 473cceef8ade1758128ddb348ec3c90216d12b3f */ + * Stub hash: f2ff49a9cefcd31a990989b1c1ff525f9fb4d3de */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql_link, mysqli, 0) @@ -576,7 +576,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_result___construct, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, mysqli_link, IS_OBJECT, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, resmode, IS_LONG, 0, "MYSQLI_STORE_RESULT") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, result_mode, IS_LONG, 0, "MYSQLI_STORE_RESULT") ZEND_END_ARG_INFO() #define arginfo_class_mysqli_result_close arginfo_class_mysqli_character_set_name From 465a121fd6dbce7b86ecc8e6834d8a8de3b12c85 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 13 Sep 2020 16:41:15 +0200 Subject: [PATCH 06/12] Address review comments --- ext/mysqli/mysqli.c | 2 +- ext/mysqli/mysqli_api.c | 7 +++---- ext/mysqli/tests/mysqli_result_invalid_mode.phpt | 4 ++-- ext/mysqli/tests/mysqli_stmt_bind_param.phpt | 12 ++++++------ ext/mysqli/tests/mysqli_stmt_field_count.phpt | 2 +- 5 files changed, 13 insertions(+), 14 deletions(-) diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index bed3619870d05..feadc1f777c10 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -1025,7 +1025,7 @@ PHP_METHOD(mysqli_result, __construct) } if (resmode != MYSQLI_STORE_RESULT && resmode != MYSQLI_USE_RESULT) { - zend_argument_value_error(2, "must be MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT"); + zend_argument_value_error(2, "must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT"); RETURN_THROWS(); } diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 73f183ed5b0b5..06c91f5dacf6e 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -332,12 +332,12 @@ PHP_FUNCTION(mysqli_stmt_bind_param) if (types_len != (size_t) argc) { /* number of bind variables doesn't match number of elements in type definition string */ - zend_argument_count_error("Number of elements in type definition string doesn't match number of bind variables"); + zend_argument_count_error("The number of elements in the type definition string must match the number of bind variables"); RETURN_THROWS(); } if (types_len != mysql_stmt_param_count(stmt->stmt)) { - zend_argument_count_error("Number of variables doesn't match number of parameters in prepared statement"); + zend_argument_count_error("The number of variables must match the number of parameters in the prepared statement"); RETURN_THROWS(); } @@ -739,13 +739,12 @@ PHP_FUNCTION(mysqli_data_seek) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered(result)) { - // TODO Promoto to Exception? + // TODO Promote to Exception? php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); RETURN_FALSE; } if ((uint64_t)offset >= mysql_num_rows(result)) { - // TODO Warning/Exception? RETURN_FALSE; } diff --git a/ext/mysqli/tests/mysqli_result_invalid_mode.phpt b/ext/mysqli/tests/mysqli_result_invalid_mode.phpt index 65c692c222445..374fccfa61e81 100644 --- a/ext/mysqli/tests/mysqli_result_invalid_mode.phpt +++ b/ext/mysqli/tests/mysqli_result_invalid_mode.phpt @@ -26,5 +26,5 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECT-- -mysqli_result::__construct(): Argument #2 ($result_mode) must be MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT -mysqli_result::__construct(): Argument #2 ($result_mode) must be MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT +mysqli_result::__construct(): Argument #2 ($result_mode) must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT +mysqli_result::__construct(): Argument #2 ($result_mode) must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt index 6c66c5a069edc..a12e01dc4203a 100644 --- a/ext/mysqli/tests/mysqli_stmt_bind_param.phpt +++ b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt @@ -416,13 +416,13 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECTF-- -Number of variables doesn't match number of parameters in prepared statement +The number of variables must match the number of parameters in the prepared statement mysqli_stmt_bind_param(): Argument #2 ($types) cannot be empty -Number of elements in type definition string doesn't match number of bind variables -Number of variables doesn't match number of parameters in prepared statement -Number of elements in type definition string doesn't match number of bind variables -Number of variables doesn't match number of parameters in prepared statement -Number of elements in type definition string doesn't match number of bind variables +The number of elements in the type definition string must match the number of bind variables +The number of variables must match the number of parameters in the prepared statement +The number of elements in the type definition string must match the number of bind variables +The number of variables must match the number of parameters in the prepared statement +The number of elements in the type definition string must match the number of bind variables Warning: mysqli_stmt_bind_param(): Undefined fieldtype a (parameter 3) in %s on line %d diff --git a/ext/mysqli/tests/mysqli_stmt_field_count.phpt b/ext/mysqli/tests/mysqli_stmt_field_count.phpt index 75afa990011d0..5c725cd063109 100644 --- a/ext/mysqli/tests/mysqli_stmt_field_count.phpt +++ b/ext/mysqli/tests/mysqli_stmt_field_count.phpt @@ -98,7 +98,7 @@ require_once('skipifconnectfailure.inc'); --EXPECT-- mysqli_stmt object is not fully initialized mysqli_stmt object is not fully initialized -Number of variables doesn't match number of parameters in prepared statement +The number of variables must match the number of parameters in the prepared statement mysqli_stmt object is already closed mysqli_stmt object is already closed done! From 0ba8865ce6b60c3fde6db5186835a26c00dd3787 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 13 Sep 2020 18:59:33 +0200 Subject: [PATCH 07/12] Maybe it's attr_get() messing stuff --- ext/mysqli/mysqli_api.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 06c91f5dacf6e..76e37001ee3ef 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -2319,20 +2319,18 @@ PHP_FUNCTION(mysqli_stmt_attr_get) zval *mysql_stmt; unsigned long value = 0; zend_long attr; + int rc; if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) { RETURN_THROWS(); } MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); - switch (attr) { + if (attr != STMT_ATTR_CURSOR_TYPE && attr != STMT_ATTR_PREFETCH_ROWS #if MYSQL_VERSION_ID >= 50107 - case STMT_ATTR_UPDATE_MAX_LENGTH: + && attr != STMT_ATTR_UPDATE_MAX_LENGTH #endif - case STMT_ATTR_CURSOR_TYPE: - case STMT_ATTR_PREFETCH_ROWS: - break; - default: + ) { zend_argument_value_error(ERROR_ARG_POS(2), "must be one of " #if MYSQL_VERSION_ID >= 50107 "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, " @@ -2341,9 +2339,12 @@ PHP_FUNCTION(mysqli_stmt_attr_get) RETURN_THROWS(); } - /* Success corresponds to 0 return value and a non-zero value - * should only happen if the attr/option is unknown */ - ZEND_ASSERT(mysql_stmt_attr_get(stmt->stmt, attr, &value) == 0); + if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) { + /* Success corresponds to 0 return value and a non-zero value + * should only happen if the attr/option is unknown */ + ZEND_UNREACHABLE(); + } + #if MYSQL_VERSION_ID >= 50107 if (attr == STMT_ATTR_UPDATE_MAX_LENGTH) From 5049bd3fdd7b7941785ac18bd4c7a89eec6e93ba Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 14 Sep 2020 05:47:50 +0200 Subject: [PATCH 08/12] Fix Linux now --- ext/mysqli/mysqli_api.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 76e37001ee3ef..91c9bf5ad6faf 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -2242,6 +2242,9 @@ PHP_FUNCTION(mysqli_stmt_attr_set) MY_STMT *stmt; zval *mysql_stmt; zend_long mode_in; +#if MYSQL_VERSION_ID >= 50107 + my_bool mode_b; +#endif unsigned long mode; zend_long attr; void *mode_p; @@ -2255,8 +2258,6 @@ PHP_FUNCTION(mysqli_stmt_attr_set) switch (attr) { #if MYSQL_VERSION_ID >= 50107 case STMT_ATTR_UPDATE_MAX_LENGTH: - { - my_bool mode_b; if (mode_in != 0 && mode_in != 1) { zend_argument_value_error(ERROR_ARG_POS(3), "must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH"); RETURN_THROWS(); @@ -2264,9 +2265,8 @@ PHP_FUNCTION(mysqli_stmt_attr_set) mode_b = (my_bool) mode_in; mode_p = &mode_b; break; - } #endif - case STMT_ATTR_CURSOR_TYPE: { + case STMT_ATTR_CURSOR_TYPE: switch (mode_in) { case CURSOR_TYPE_NO_CURSOR: case CURSOR_TYPE_READ_ONLY: @@ -2282,7 +2282,6 @@ PHP_FUNCTION(mysqli_stmt_attr_set) mode = mode_in; mode_p = &mode; break; - } case STMT_ATTR_PREFETCH_ROWS: if (mode_in < 1) { zend_argument_value_error(ERROR_ARG_POS(3), "must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS"); From ba93066019d54089e082489ad33f17d2cdcd3780 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Mon, 14 Sep 2020 18:43:03 +0200 Subject: [PATCH 09/12] Address reviews --- ext/mysqli/mysqli.c | 9 ++---- ext/mysqli/mysqli_api.c | 30 +++++++------------ ext/mysqli/mysqli_nonapi.c | 18 ++++------- ext/mysqli/tests/bug55582.phpt | 22 ++++++++------ ext/mysqli/tests/bug74595.phpt | 25 ---------------- .../tests/mysqli_begin_transaction.phpt | 2 +- ext/mysqli/tests/mysqli_data_seek.phpt | 12 ++++---- ext/mysqli/tests/mysqli_data_seek_oo.phpt | 12 ++++---- .../tests/mysqli_fetch_field_direct.phpt | 11 ++++--- .../tests/mysqli_fetch_field_direct_oo.phpt | 11 ++++--- ext/mysqli/tests/mysqli_num_rows.phpt | 12 ++++---- ext/mysqli/tests/mysqli_query.phpt | 2 +- ext/mysqli/tests/mysqli_use_result.phpt | 12 ++++---- 13 files changed, 75 insertions(+), 103 deletions(-) delete mode 100644 ext/mysqli/tests/bug74595.phpt diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index feadc1f777c10..e056ceba2dabd 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -1024,11 +1024,6 @@ PHP_METHOD(mysqli_result, __construct) RETURN_THROWS(); } - if (resmode != MYSQLI_STORE_RESULT && resmode != MYSQLI_USE_RESULT) { - zend_argument_value_error(2, "must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT"); - RETURN_THROWS(); - } - MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); switch (resmode) { @@ -1038,7 +1033,9 @@ PHP_METHOD(mysqli_result, __construct) case MYSQLI_USE_RESULT: result = mysql_use_result(mysql->mysql); break; - EMPTY_SWITCH_DEFAULT_CASE(); + default: + zend_argument_value_error(2, "must be either MYSQLI_STORE_RESULT or MYSQLI_USE_RESULT"); + RETURN_THROWS(); } if (!result) { diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 91c9bf5ad6faf..687aced25b3cb 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -739,9 +739,8 @@ PHP_FUNCTION(mysqli_data_seek) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered(result)) { - // TODO Promote to Exception? - php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); - RETURN_FALSE; + zend_throw_error(NULL, "Function cannot be used with MYSQL_USE_RESULT"); + RETURN_THROWS(); } if ((uint64_t)offset >= mysql_num_rows(result)) { @@ -1197,9 +1196,8 @@ PHP_FUNCTION(mysqli_fetch_field_direct) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (offset >= (zend_long) mysql_num_fields(result)) { - // TODO ValueError? - php_error_docref(NULL, E_WARNING, "Field offset is invalid for resultset"); - RETURN_FALSE; + zend_argument_value_error(ERROR_ARG_POS(2), "must be less than the number of fields for this result set"); + RETURN_THROWS(); } if (!(field = mysql_fetch_field_direct(result,offset))) { @@ -1624,9 +1622,8 @@ PHP_FUNCTION(mysqli_num_rows) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) { - // TODO Exception? - php_error_docref(NULL, E_WARNING, "Function cannot be used with MYSQL_USE_RESULT"); - RETURN_LONG(0); + zend_throw_error(NULL, "Function cannot be used with MYSQL_USE_RESULT"); + RETURN_THROWS(); } MYSQLI_RETURN_LONG_INT(mysql_num_rows(result)); @@ -2323,25 +2320,18 @@ PHP_FUNCTION(mysqli_stmt_attr_get) if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Ol", &mysql_stmt, mysqli_stmt_class_entry, &attr) == FAILURE) { RETURN_THROWS(); } + MYSQLI_FETCH_RESOURCE_STMT(stmt, mysql_stmt, MYSQLI_STATUS_VALID); - if (attr != STMT_ATTR_CURSOR_TYPE && attr != STMT_ATTR_PREFETCH_ROWS -#if MYSQL_VERSION_ID >= 50107 - && attr != STMT_ATTR_UPDATE_MAX_LENGTH -#endif - ) { + if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) { + /* Success corresponds to 0 return value and a non-zero value + * should only happen if the attr/option is unknown */ zend_argument_value_error(ERROR_ARG_POS(2), "must be one of " #if MYSQL_VERSION_ID >= 50107 "MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, " #endif "MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE"); RETURN_THROWS(); - } - - if ((rc = mysql_stmt_attr_get(stmt->stmt, attr, &value))) { - /* Success corresponds to 0 return value and a non-zero value - * should only happen if the attr/option is unknown */ - ZEND_UNREACHABLE(); } diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 5880c288d8d19..870bc335a9dc8 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -636,18 +636,13 @@ PHP_FUNCTION(mysqli_query) RETURN_THROWS(); } if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && - MYSQLI_STORE_RESULT != - #ifdef MYSQLI_USE_MYSQLND - (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) - #else - (resultmode & ~MYSQLI_ASYNC) - #endif + MYSQLI_STORE_RESULT != (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) ) { - zend_argument_value_error(ERROR_ARG_POS(3), "must be one of " + zend_argument_value_error(ERROR_ARG_POS(3), "must be either MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT" #ifdef MYSQLI_USE_MYSQLND - "MYSQLI_ASYNC," + " with MYSQLI_ASYNC as an optional bitmask flags" #endif - "MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT"); + ); RETURN_THROWS(); } @@ -1172,10 +1167,7 @@ PHP_FUNCTION(mysqli_begin_transaction) } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); if (flags < 0) { - zend_argument_value_error(ERROR_ARG_POS(2), "must be one of MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT" - /* TODO Only MySQL 5.6 and later */ - ", MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE" - ); + zend_argument_value_error(ERROR_ARG_POS(2), "must be one of the MYSQLI_TRANS_* constant"); RETURN_THROWS(); } if (!name_len) { diff --git a/ext/mysqli/tests/bug55582.phpt b/ext/mysqli/tests/bug55582.phpt index 86626c0279f79..c12bed08ca4dd 100644 --- a/ext/mysqli/tests/bug55582.phpt +++ b/ext/mysqli/tests/bug55582.phpt @@ -15,27 +15,31 @@ require_once("connect.inc"); var_dump($link->real_query("SELECT 1")); $res = $link->use_result(); - var_dump(mysqli_num_rows($res)); + try { + var_dump(mysqli_num_rows($res)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } var_dump($res->fetch_assoc()); - var_dump(mysqli_num_rows($res)); + try { + var_dump(mysqli_num_rows($res)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } var_dump($res->fetch_assoc()); var_dump(mysqli_num_rows($res)); $link->close(); echo "done\n"; ?> ---EXPECTF-- +--EXPECT-- bool(true) - -Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d -int(0) +Function cannot be used with MYSQL_USE_RESULT array(1) { [1]=> string(1) "1" } - -Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d -int(0) +Function cannot be used with MYSQL_USE_RESULT NULL int(1) done diff --git a/ext/mysqli/tests/bug74595.phpt b/ext/mysqli/tests/bug74595.phpt deleted file mode 100644 index 0fdebc7027f9e..0000000000000 --- a/ext/mysqli/tests/bug74595.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Bug #74595 (ReflectionMethod::getParameters returns incorrect number of parameters) ---SKIPIF-- - ---FILE-- -getMethod('query'); -var_dump($method->getParameters()); -?> ---EXPECTF-- -array(2) { - [0]=> - object(ReflectionParameter)#%d (1) { - ["name"]=> - string(5) "query" - } - [1]=> - object(ReflectionParameter)#%d (1) { - ["name"]=> - string(11) "result_mode" - } -} diff --git a/ext/mysqli/tests/mysqli_begin_transaction.phpt b/ext/mysqli/tests/mysqli_begin_transaction.phpt index 3d314aee26044..53a53b75f2b53 100644 --- a/ext/mysqli/tests/mysqli_begin_transaction.phpt +++ b/ext/mysqli/tests/mysqli_begin_transaction.phpt @@ -101,5 +101,5 @@ if (!have_innodb($link)) ?> --EXPECT-- NULL -mysqli_begin_transaction(): Argument #2 ($flags) must be one of MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT, MYSQLI_TRANS_START_READ_ONLY, or MYSQLI_TRANS_START_READ_WRITE +mysqli_begin_transaction(): Argument #2 ($flags) must be one of the MYSQLI_TRANS_* constant done! diff --git a/ext/mysqli/tests/mysqli_data_seek.phpt b/ext/mysqli/tests/mysqli_data_seek.phpt index 5a6587449b155..64c7c712ec571 100644 --- a/ext/mysqli/tests/mysqli_data_seek.phpt +++ b/ext/mysqli/tests/mysqli_data_seek.phpt @@ -42,8 +42,11 @@ require_once('skipifconnectfailure.inc'); if (!$res = mysqli_query($link, 'SELECT * FROM test ORDER BY id', MYSQLI_USE_RESULT)) printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); - if (false !== ($tmp = mysqli_data_seek($res, 3))) - printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + var_dump(mysqli_data_seek($res, 3)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_free_result($res); @@ -61,9 +64,8 @@ require_once('skipifconnectfailure.inc'); ---EXPECTF-- +--EXPECT-- mysqli_data_seek(): Argument #2 ($offset) must be greater than or equal to 0 - -Warning: mysqli_data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d +Function cannot be used with MYSQL_USE_RESULT mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_data_seek_oo.phpt b/ext/mysqli/tests/mysqli_data_seek_oo.phpt index 55561f95032e2..df4145b275b65 100644 --- a/ext/mysqli/tests/mysqli_data_seek_oo.phpt +++ b/ext/mysqli/tests/mysqli_data_seek_oo.phpt @@ -54,8 +54,11 @@ require_once('skipifconnectfailure.inc'); if (!$res = $mysqli->query('SELECT * FROM test ORDER BY id', MYSQLI_USE_RESULT)) printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); - if (false !== ($tmp = $res->data_seek(3))) - printf("[014] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); + try { + var_dump($res->data_seek(3)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } $res->free_result(); @@ -72,10 +75,9 @@ require_once('skipifconnectfailure.inc'); ---EXPECTF-- +--EXPECT-- mysqli_result object is already closed mysqli_result::data_seek(): Argument #1 ($offset) must be greater than or equal to 0 - -Warning: mysqli_result::data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d +Function cannot be used with MYSQL_USE_RESULT mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_fetch_field_direct.phpt b/ext/mysqli/tests/mysqli_fetch_field_direct.phpt index ad02eccfdc0bf..8b57cca094c81 100644 --- a/ext/mysqli/tests/mysqli_fetch_field_direct.phpt +++ b/ext/mysqli/tests/mysqli_fetch_field_direct.phpt @@ -22,7 +22,12 @@ require_once('skipifconnectfailure.inc'); echo $e->getMessage() . \PHP_EOL; } var_dump(mysqli_fetch_field_direct($res, 0)); - var_dump(mysqli_fetch_field_direct($res, 2)); + + try { + var_dump(mysqli_fetch_field_direct($res, 2)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_free_result($res); @@ -69,8 +74,6 @@ object(stdClass)#%d (13) { ["decimals"]=> int(%d) } - -Warning: mysqli_fetch_field_direct(): Field offset is invalid for resultset in %s on line %d -bool(false) +mysqli_fetch_field_direct(): Argument #2 ($offset) must be less than the number of fields for this result set mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt b/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt index cb13f946734a5..5dedefcdab1b9 100644 --- a/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt +++ b/ext/mysqli/tests/mysqli_fetch_field_direct_oo.phpt @@ -34,7 +34,12 @@ require_once('skipifconnectfailure.inc'); } var_dump($res->fetch_field_direct(0)); - var_dump($res->fetch_field_direct(2)); + + try { + var_dump($res->fetch_field_direct(2)); + } catch (\ValueError $e) { + echo $e->getMessage() . \PHP_EOL; + } $res->free_result(); @@ -82,8 +87,6 @@ object(stdClass)#%d (13) { ["decimals"]=> int(%d) } - -Warning: mysqli_result::fetch_field_direct(): Field offset is invalid for resultset in %s on line %d -bool(false) +mysqli_result::fetch_field_direct(): Argument #1 ($field_nr) must be less than the number of fields for this result set mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_num_rows.phpt b/ext/mysqli/tests/mysqli_num_rows.phpt index 3266f37dce172..e2834e5883f70 100644 --- a/ext/mysqli/tests/mysqli_num_rows.phpt +++ b/ext/mysqli/tests/mysqli_num_rows.phpt @@ -56,8 +56,11 @@ require_once('skipifconnectfailure.inc'); if ($res = mysqli_query($link, 'SELECT id FROM test', MYSQLI_USE_RESULT)) { $row = mysqli_fetch_row($res); - if (0 !== ($tmp = mysqli_num_rows($res))) - printf("[031] Expecting int/0, got %s/%d\n", gettype($tmp), $tmp); + try { + var_dump(mysqli_num_rows($res)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_free_result($res); } else { @@ -71,12 +74,11 @@ require_once('skipifconnectfailure.inc'); ---EXPECTF-- +--EXPECT-- mysqli_result object is already closed mysqli_result object is already closed mysqli_result object is already closed mysqli_result object is already closed run_tests.php don't fool me with your 'ungreedy' expression '.+?'! - -Warning: mysqli_num_rows(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d +Function cannot be used with MYSQL_USE_RESULT done! diff --git a/ext/mysqli/tests/mysqli_query.phpt b/ext/mysqli/tests/mysqli_query.phpt index 9b8d8e9f9b10c..08b5d6b65f837 100644 --- a/ext/mysqli/tests/mysqli_query.phpt +++ b/ext/mysqli/tests/mysqli_query.phpt @@ -126,6 +126,6 @@ array(1) { string(1) "a" } string(1) "a" -mysqli_query(): Argument #3 ($result_mode) must be one of MYSQLI_ASYNC,MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT +mysqli_query(): Argument #3 ($result_mode) must be either MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT with MYSQLI_ASYNC as an optional bitmask flags mysqli object is already closed done! diff --git a/ext/mysqli/tests/mysqli_use_result.phpt b/ext/mysqli/tests/mysqli_use_result.phpt index 1b679d142d3a4..de4fe791f8f00 100644 --- a/ext/mysqli/tests/mysqli_use_result.phpt +++ b/ext/mysqli/tests/mysqli_use_result.phpt @@ -19,9 +19,11 @@ require_once('skipifconnectfailure.inc'); printf("[004] Expecting object, got %s/%s. [%d] %s\n", gettype($res), $res, mysqli_errno($link), mysqli_error($link)); - if (false !== ($tmp = mysqli_data_seek($res, 2))) - printf("[005] Expecting boolean/true, got %s/%s. [%d] %s\n", - gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link)); + try { + var_dump(mysqli_data_seek($res, 2)); + } catch (\Error $e) { + echo $e->getMessage() . \PHP_EOL; + } mysqli_free_result($res); @@ -53,7 +55,7 @@ require_once('skipifconnectfailure.inc'); ---EXPECTF-- -Warning: mysqli_data_seek(): Function cannot be used with MYSQL_USE_RESULT in %s on line %d +--EXPECT-- +Function cannot be used with MYSQL_USE_RESULT mysqli object is already closed done! From 7dd2cd30d2deb82d67e2d2a65b4303eb7deb7ea8 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 15 Sep 2020 15:52:35 +0200 Subject: [PATCH 10/12] Nits --- ext/mysqli/mysqli.stub.php | 2 +- ext/mysqli/mysqli_api.c | 8 ++++++-- ext/mysqli/mysqli_arginfo.h | 4 ++-- ext/mysqli/mysqli_nonapi.c | 4 ++-- ext/mysqli/tests/bug55582.phpt | 4 ++-- ext/mysqli/tests/mysqli_begin_transaction.phpt | 2 +- ext/mysqli/tests/mysqli_data_seek.phpt | 2 +- ext/mysqli/tests/mysqli_data_seek_oo.phpt | 2 +- ext/mysqli/tests/mysqli_num_rows.phpt | 2 +- ext/mysqli/tests/mysqli_query.phpt | 2 +- ext/mysqli/tests/mysqli_use_result.phpt | 2 +- 11 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 6b2c70341432a..de74bba8e128f 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -682,7 +682,7 @@ function mysqli_stmt_bind_result(mysqli_stmt $mysql_stmt, mixed &...$vars): bool function mysqli_stmt_close(mysqli_stmt $mysql_stmt): bool {} -function mysqli_stmt_data_seek(mysqli_stmt $mysql_stmt, int $offset): ?bool {} +function mysqli_stmt_data_seek(mysqli_stmt $mysql_stmt, int $offset): void {} function mysqli_stmt_errno(mysqli_stmt $mysql_stmt): int {} diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 687aced25b3cb..2b65a755eebab 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -739,7 +739,11 @@ PHP_FUNCTION(mysqli_data_seek) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered(result)) { - zend_throw_error(NULL, "Function cannot be used with MYSQL_USE_RESULT"); + if (getThis()) { + zend_throw_error(NULL, "mysqli_result::data_seek() cannot be used with MYSQL_USE_RESULT"); + } else { + zend_throw_error(NULL, "mysqli_data_seek() cannot be used with MYSQL_USE_RESULT"); + } RETURN_THROWS(); } @@ -1622,7 +1626,7 @@ PHP_FUNCTION(mysqli_num_rows) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) { - zend_throw_error(NULL, "Function cannot be used with MYSQL_USE_RESULT"); + zend_throw_error(NULL, "mysqli_num_rows() cannot be used with MYSQL_USE_RESULT"); RETURN_THROWS(); } diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index dab786bc458a3..15daa38426a18 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: f2ff49a9cefcd31a990989b1c1ff525f9fb4d3de */ + * Stub hash: beb821b6e0b26f798d88f7b726a39084d856251f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING) ZEND_ARG_OBJ_INFO(0, mysql_link, mysqli, 0) @@ -309,7 +309,7 @@ ZEND_END_ARG_INFO() #define arginfo_mysqli_stmt_close arginfo_mysqli_stmt_execute -ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_data_seek, 0, 2, _IS_BOOL, 1) +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_stmt_data_seek, 0, 2, IS_VOID, 0) ZEND_ARG_OBJ_INFO(0, mysql_stmt, mysqli_stmt, 0) ZEND_ARG_TYPE_INFO(0, offset, IS_LONG, 0) ZEND_END_ARG_INFO() diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 870bc335a9dc8..394afc7ccc993 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -640,7 +640,7 @@ PHP_FUNCTION(mysqli_query) ) { zend_argument_value_error(ERROR_ARG_POS(3), "must be either MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT" #ifdef MYSQLI_USE_MYSQLND - " with MYSQLI_ASYNC as an optional bitmask flags" + " with MYSQLI_ASYNC as an optional bitmask flag" #endif ); RETURN_THROWS(); @@ -1167,7 +1167,7 @@ PHP_FUNCTION(mysqli_begin_transaction) } MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_VALID); if (flags < 0) { - zend_argument_value_error(ERROR_ARG_POS(2), "must be one of the MYSQLI_TRANS_* constant"); + zend_argument_value_error(ERROR_ARG_POS(2), "must be one of the MYSQLI_TRANS_* constants"); RETURN_THROWS(); } if (!name_len) { diff --git a/ext/mysqli/tests/bug55582.phpt b/ext/mysqli/tests/bug55582.phpt index c12bed08ca4dd..b22b9b7d707f8 100644 --- a/ext/mysqli/tests/bug55582.phpt +++ b/ext/mysqli/tests/bug55582.phpt @@ -34,12 +34,12 @@ require_once("connect.inc"); ?> --EXPECT-- bool(true) -Function cannot be used with MYSQL_USE_RESULT +mysqli_num_rows() cannot be used with MYSQL_USE_RESULT array(1) { [1]=> string(1) "1" } -Function cannot be used with MYSQL_USE_RESULT +mysqli_num_rows() cannot be used with MYSQL_USE_RESULT NULL int(1) done diff --git a/ext/mysqli/tests/mysqli_begin_transaction.phpt b/ext/mysqli/tests/mysqli_begin_transaction.phpt index 53a53b75f2b53..7a9107b7e6917 100644 --- a/ext/mysqli/tests/mysqli_begin_transaction.phpt +++ b/ext/mysqli/tests/mysqli_begin_transaction.phpt @@ -101,5 +101,5 @@ if (!have_innodb($link)) ?> --EXPECT-- NULL -mysqli_begin_transaction(): Argument #2 ($flags) must be one of the MYSQLI_TRANS_* constant +mysqli_begin_transaction(): Argument #2 ($flags) must be one of the MYSQLI_TRANS_* constants done! diff --git a/ext/mysqli/tests/mysqli_data_seek.phpt b/ext/mysqli/tests/mysqli_data_seek.phpt index 64c7c712ec571..88652919c7e40 100644 --- a/ext/mysqli/tests/mysqli_data_seek.phpt +++ b/ext/mysqli/tests/mysqli_data_seek.phpt @@ -66,6 +66,6 @@ require_once('skipifconnectfailure.inc'); ?> --EXPECT-- mysqli_data_seek(): Argument #2 ($offset) must be greater than or equal to 0 -Function cannot be used with MYSQL_USE_RESULT +mysqli_data_seek() cannot be used with MYSQL_USE_RESULT mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_data_seek_oo.phpt b/ext/mysqli/tests/mysqli_data_seek_oo.phpt index df4145b275b65..529224fade0aa 100644 --- a/ext/mysqli/tests/mysqli_data_seek_oo.phpt +++ b/ext/mysqli/tests/mysqli_data_seek_oo.phpt @@ -78,6 +78,6 @@ require_once('skipifconnectfailure.inc'); --EXPECT-- mysqli_result object is already closed mysqli_result::data_seek(): Argument #1 ($offset) must be greater than or equal to 0 -Function cannot be used with MYSQL_USE_RESULT +mysqli_result::data_seek() cannot be used with MYSQL_USE_RESULT mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_num_rows.phpt b/ext/mysqli/tests/mysqli_num_rows.phpt index e2834e5883f70..c5ab91c376020 100644 --- a/ext/mysqli/tests/mysqli_num_rows.phpt +++ b/ext/mysqli/tests/mysqli_num_rows.phpt @@ -80,5 +80,5 @@ mysqli_result object is already closed mysqli_result object is already closed mysqli_result object is already closed run_tests.php don't fool me with your 'ungreedy' expression '.+?'! -Function cannot be used with MYSQL_USE_RESULT +mysqli_num_rows() cannot be used with MYSQL_USE_RESULT done! diff --git a/ext/mysqli/tests/mysqli_query.phpt b/ext/mysqli/tests/mysqli_query.phpt index 08b5d6b65f837..daac374cf7976 100644 --- a/ext/mysqli/tests/mysqli_query.phpt +++ b/ext/mysqli/tests/mysqli_query.phpt @@ -126,6 +126,6 @@ array(1) { string(1) "a" } string(1) "a" -mysqli_query(): Argument #3 ($result_mode) must be either MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT with MYSQLI_ASYNC as an optional bitmask flags +mysqli_query(): Argument #3 ($result_mode) must be either MYSQLI_USE_RESULT, or MYSQLI_STORE_RESULT with MYSQLI_ASYNC as an optional bitmask flag mysqli object is already closed done! diff --git a/ext/mysqli/tests/mysqli_use_result.phpt b/ext/mysqli/tests/mysqli_use_result.phpt index de4fe791f8f00..b96c66bc20f69 100644 --- a/ext/mysqli/tests/mysqli_use_result.phpt +++ b/ext/mysqli/tests/mysqli_use_result.phpt @@ -56,6 +56,6 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECT-- -Function cannot be used with MYSQL_USE_RESULT +mysqli_data_seek() cannot be used with MYSQL_USE_RESULT mysqli object is already closed done! From 8a81c504ae3fdf28dac4570a0e0bd5a939b6faa9 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 15 Sep 2020 17:53:16 +0200 Subject: [PATCH 11/12] Fix OpCache --- ext/opcache/Optimizer/zend_func_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/opcache/Optimizer/zend_func_info.c b/ext/opcache/Optimizer/zend_func_info.c index 90fb4d9b73f57..6f2edfb6ca4b5 100644 --- a/ext/opcache/Optimizer/zend_func_info.c +++ b/ext/opcache/Optimizer/zend_func_info.c @@ -488,7 +488,7 @@ static const func_info_t func_infos[] = { F1("mysqli_prepare", MAY_BE_FALSE | MAY_BE_OBJECT), F1("mysqli_real_escape_string", MAY_BE_STRING), F1("mysqli_stmt_affected_rows", MAY_BE_LONG | MAY_BE_STRING), - F0("mysqli_stmt_data_seek", MAY_BE_NULL | MAY_BE_FALSE), + F0("mysqli_stmt_data_seek", MAY_BE_NULL), F1("mysqli_stmt_insert_id", MAY_BE_LONG | MAY_BE_STRING), F1("mysqli_stmt_num_rows", MAY_BE_LONG | MAY_BE_STRING), F1("mysqli_sqlstate", MAY_BE_NULL | MAY_BE_STRING), From 85ab28b649b4a2e6e9c4b1269dca3552ef4e020a Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Tue, 15 Sep 2020 18:11:51 +0200 Subject: [PATCH 12/12] Nit: Use MYSQLI_USE_RESULT --- ext/mysqli/mysqli_api.c | 6 +++--- ext/mysqli/tests/bug55582.phpt | 4 ++-- ext/mysqli/tests/mysqli_data_seek.phpt | 2 +- ext/mysqli/tests/mysqli_data_seek_oo.phpt | 2 +- ext/mysqli/tests/mysqli_num_rows.phpt | 2 +- ext/mysqli/tests/mysqli_use_result.phpt | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 2b65a755eebab..88e6e91cd151a 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -740,9 +740,9 @@ PHP_FUNCTION(mysqli_data_seek) if (mysqli_result_is_unbuffered(result)) { if (getThis()) { - zend_throw_error(NULL, "mysqli_result::data_seek() cannot be used with MYSQL_USE_RESULT"); + zend_throw_error(NULL, "mysqli_result::data_seek() cannot be used with MYSQLI_USE_RESULT"); } else { - zend_throw_error(NULL, "mysqli_data_seek() cannot be used with MYSQL_USE_RESULT"); + zend_throw_error(NULL, "mysqli_data_seek() cannot be used with MYSQLI_USE_RESULT"); } RETURN_THROWS(); } @@ -1626,7 +1626,7 @@ PHP_FUNCTION(mysqli_num_rows) MYSQLI_FETCH_RESOURCE(result, MYSQL_RES *, mysql_result, "mysqli_result", MYSQLI_STATUS_VALID); if (mysqli_result_is_unbuffered_and_not_everything_is_fetched(result)) { - zend_throw_error(NULL, "mysqli_num_rows() cannot be used with MYSQL_USE_RESULT"); + zend_throw_error(NULL, "mysqli_num_rows() cannot be used with MYSQLI_USE_RESULT"); RETURN_THROWS(); } diff --git a/ext/mysqli/tests/bug55582.phpt b/ext/mysqli/tests/bug55582.phpt index b22b9b7d707f8..817f7eecfe557 100644 --- a/ext/mysqli/tests/bug55582.phpt +++ b/ext/mysqli/tests/bug55582.phpt @@ -34,12 +34,12 @@ require_once("connect.inc"); ?> --EXPECT-- bool(true) -mysqli_num_rows() cannot be used with MYSQL_USE_RESULT +mysqli_num_rows() cannot be used with MYSQLI_USE_RESULT array(1) { [1]=> string(1) "1" } -mysqli_num_rows() cannot be used with MYSQL_USE_RESULT +mysqli_num_rows() cannot be used with MYSQLI_USE_RESULT NULL int(1) done diff --git a/ext/mysqli/tests/mysqli_data_seek.phpt b/ext/mysqli/tests/mysqli_data_seek.phpt index 88652919c7e40..2b477af3fd4b1 100644 --- a/ext/mysqli/tests/mysqli_data_seek.phpt +++ b/ext/mysqli/tests/mysqli_data_seek.phpt @@ -66,6 +66,6 @@ require_once('skipifconnectfailure.inc'); ?> --EXPECT-- mysqli_data_seek(): Argument #2 ($offset) must be greater than or equal to 0 -mysqli_data_seek() cannot be used with MYSQL_USE_RESULT +mysqli_data_seek() cannot be used with MYSQLI_USE_RESULT mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_data_seek_oo.phpt b/ext/mysqli/tests/mysqli_data_seek_oo.phpt index 529224fade0aa..ccbf86542ac59 100644 --- a/ext/mysqli/tests/mysqli_data_seek_oo.phpt +++ b/ext/mysqli/tests/mysqli_data_seek_oo.phpt @@ -78,6 +78,6 @@ require_once('skipifconnectfailure.inc'); --EXPECT-- mysqli_result object is already closed mysqli_result::data_seek(): Argument #1 ($offset) must be greater than or equal to 0 -mysqli_result::data_seek() cannot be used with MYSQL_USE_RESULT +mysqli_result::data_seek() cannot be used with MYSQLI_USE_RESULT mysqli_result object is already closed done! diff --git a/ext/mysqli/tests/mysqli_num_rows.phpt b/ext/mysqli/tests/mysqli_num_rows.phpt index c5ab91c376020..4d09c256823a7 100644 --- a/ext/mysqli/tests/mysqli_num_rows.phpt +++ b/ext/mysqli/tests/mysqli_num_rows.phpt @@ -80,5 +80,5 @@ mysqli_result object is already closed mysqli_result object is already closed mysqli_result object is already closed run_tests.php don't fool me with your 'ungreedy' expression '.+?'! -mysqli_num_rows() cannot be used with MYSQL_USE_RESULT +mysqli_num_rows() cannot be used with MYSQLI_USE_RESULT done! diff --git a/ext/mysqli/tests/mysqli_use_result.phpt b/ext/mysqli/tests/mysqli_use_result.phpt index b96c66bc20f69..c309d3e3910b5 100644 --- a/ext/mysqli/tests/mysqli_use_result.phpt +++ b/ext/mysqli/tests/mysqli_use_result.phpt @@ -56,6 +56,6 @@ require_once('skipifconnectfailure.inc'); require_once("clean_table.inc"); ?> --EXPECT-- -mysqli_data_seek() cannot be used with MYSQL_USE_RESULT +mysqli_data_seek() cannot be used with MYSQLI_USE_RESULT mysqli object is already closed done!