summaryrefslogtreecommitdiff
path: root/ext/mysqli
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysqli')
-rw-r--r--ext/mysqli/mysqli.c34
-rw-r--r--ext/mysqli/mysqli_api.c208
-rw-r--r--ext/mysqli/mysqli_fe.c19
-rw-r--r--ext/mysqli/mysqli_fe.h1
-rw-r--r--ext/mysqli/mysqli_nonapi.c78
-rw-r--r--ext/mysqli/mysqli_priv.h2
-rw-r--r--ext/mysqli/mysqli_prop.c6
-rw-r--r--ext/mysqli/mysqli_warning.c2
-rw-r--r--ext/mysqli/php_mysqli_structs.h5
-rw-r--r--ext/mysqli/tests/bug66043.phpt4
-rw-r--r--ext/mysqli/tests/bug66762.phpt27
-rw-r--r--ext/mysqli/tests/mysqli_begin_transaction.phpt126
-rw-r--r--ext/mysqli/tests/mysqli_change_user.phpt92
-rw-r--r--ext/mysqli/tests/mysqli_change_user_new.phpt44
-rw-r--r--ext/mysqli/tests/mysqli_change_user_old.phpt119
-rw-r--r--ext/mysqli/tests/mysqli_change_user_oo.phpt3
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt9
-rw-r--r--ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt4
-rw-r--r--ext/mysqli/tests/mysqli_commit_oo.phpt60
-rw-r--r--ext/mysqli/tests/mysqli_constants.phpt4
-rw-r--r--ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt4
-rw-r--r--ext/mysqli/tests/mysqli_fetch_all.phpt20
-rw-r--r--ext/mysqli/tests/mysqli_fetch_lengths.phpt6
-rw-r--r--ext/mysqli/tests/mysqli_pconn_max_links.phpt98
-rw-r--r--ext/mysqli/tests/mysqli_poll.phpt31
-rw-r--r--ext/mysqli/tests/mysqli_poll_kill.phpt27
-rw-r--r--ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt6
-rw-r--r--ext/mysqli/tests/mysqli_reap_async_query.phpt97
-rw-r--r--ext/mysqli/tests/mysqli_release_savepoint.phpt84
-rw-r--r--ext/mysqli/tests/mysqli_report.phpt5
-rw-r--r--ext/mysqli/tests/mysqli_report_new.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_report_wo_ps.phpt9
-rw-r--r--ext/mysqli/tests/mysqli_savepoint.phpt72
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_warnings.phpt31
-rw-r--r--ext/mysqli/tests/mysqli_store_result_buffered_c.phpt41
-rw-r--r--ext/mysqli/tests/mysqli_store_result_copy.phpt285
36 files changed, 1485 insertions, 228 deletions
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 7785fff58a..c3162f6f8f 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -176,8 +176,11 @@ void php_clear_stmt_bind(MY_STMT *stmt TSRMLS_DC)
php_free_stmt_bind_buffer(stmt->param, FETCH_SIMPLE);
/* Clean output bind */
php_free_stmt_bind_buffer(stmt->result, FETCH_RESULT);
-#endif
+ if (stmt->link_handle) {
+ zend_objects_store_del_ref_by_handle(stmt->link_handle TSRMLS_CC);
+ }
+#endif
if (stmt->query) {
efree(stmt->query);
}
@@ -558,6 +561,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY_EX("mysqli.max_links", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_links, zend_mysqli_globals, mysqli_globals, display_link_numbers)
STD_PHP_INI_ENTRY_EX("mysqli.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_mysqli_globals, mysqli_globals, display_link_numbers)
STD_PHP_INI_BOOLEAN("mysqli.allow_persistent", "1", PHP_INI_SYSTEM, OnUpdateLong, allow_persistent, zend_mysqli_globals, mysqli_globals)
+ STD_PHP_INI_BOOLEAN("mysqli.rollback_on_cached_plink", "0",PHP_INI_SYSTEM, OnUpdateBool, rollback_on_cached_plink, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_host", NULL, PHP_INI_ALL, OnUpdateString, default_host, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_user", NULL, PHP_INI_ALL, OnUpdateString, default_user, zend_mysqli_globals, mysqli_globals)
STD_PHP_INI_ENTRY("mysqli.default_pw", NULL, PHP_INI_ALL, OnUpdateString, default_pw, zend_mysqli_globals, mysqli_globals)
@@ -597,6 +601,7 @@ static PHP_GINIT_FUNCTION(mysqli)
#else
mysqli_globals->embedded = 0;
#endif
+ mysqli_globals->rollback_on_cached_plink = FALSE;
}
/* }}} */
@@ -716,6 +721,7 @@ PHP_MINIT_FUNCTION(mysqli)
REGISTER_LONG_CONSTANT("MYSQLI_USE_RESULT", MYSQLI_USE_RESULT, CONST_CS | CONST_PERSISTENT);
#if defined (MYSQLI_USE_MYSQLND)
REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("MYSQLI_STORE_RESULT_COPY_DATA", MYSQLI_STORE_RESULT_COPY_DATA, CONST_CS | CONST_PERSISTENT);
#endif
/* for mysqli_fetch_assoc */
@@ -1069,6 +1075,10 @@ PHP_FUNCTION(mysqli_stmt_construct)
efree(stmt);
RETURN_FALSE;
}
+#ifndef MYSQLI_USE_MYSQLND
+ stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
+ zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
+#endif
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = (void *)stmt;
@@ -1287,20 +1297,12 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
fci.symbol_table = NULL;
fci.object_ptr = return_value;
fci.retval_ptr_ptr = &retval_ptr;
+ fci.params = NULL;
+ fci.param_count = 0;
+ fci.no_separation = 1;
+
if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
- if (Z_TYPE_P(ctor_params) == IS_ARRAY) {
- HashTable *params_ht = Z_ARRVAL_P(ctor_params);
- uint idx;
- Bucket *p;
-
- fci.param_count = 0;
- fci.params = safe_emalloc(sizeof(zval*), params_ht->nNumOfElements, 0);
- for (idx = 0; idx < params_ht->nNumUsed; idx++) {
- p = params_ht->arData + idx;
- if (!p->xData) continue;
- fci.params[fci.param_count++] = (zval**)&p->xData;
- }
- } else {
+ if (zend_fcall_info_args(&fci, ctor_params TSRMLS_CC) == FAILURE) {
/* Two problems why we throw exceptions here: PHP is typeless
* and hence passing one argument that's not an array could be
* by mistake and the other way round is possible, too. The
@@ -1310,11 +1312,7 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
zend_throw_exception(zend_exception_get_default(TSRMLS_C), "Parameter ctor_params must be an array", 0 TSRMLS_CC);
return;
}
- } else {
- fci.param_count = 0;
- fci.params = NULL;
}
- fci.no_separation = 1;
fcc.initialized = 1;
fcc.function_handler = ce->constructor;
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 00a0b93622..766eeda59b 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -34,6 +34,111 @@
#include "php_mysqli_structs.h"
#include "mysqli_priv.h"
+
+#if !defined(MYSQLI_USE_MYSQLND)
+/* {{{ mysqli_tx_cor_options_to_string */
+static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str * str, const unsigned int mode)
+{
+ if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
+ if (str->len) {
+ smart_str_appendl(str, " ", sizeof(" ") - 1);
+ }
+ smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
+ } else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
+ if (str->len) {
+ smart_str_appendl(str, " ", sizeof(" ") - 1);
+ }
+ smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
+ }
+
+ if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
+ if (str->len) {
+ smart_str_appendl(str, " ", sizeof(" ") - 1);
+ }
+ smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
+ } else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
+ if (str->len) {
+ smart_str_appendl(str, " ", sizeof(" ") - 1);
+ }
+ smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
+ }
+ smart_str_0(str);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_escape_string_for_tx_name_in_comment */
+char *
+mysqli_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC)
+{
+ char * ret = NULL;
+ if (name) {
+ zend_bool warned = FALSE;
+ const char * p_orig = name;
+ char * p_copy;
+ p_copy = ret = emalloc(strlen(name) + 1 + 2 + 2 + 1); /* space, open, close, NullS */
+ *p_copy++ = ' ';
+ *p_copy++ = '/';
+ *p_copy++ = '*';
+ while (1) {
+ register char v = *p_orig;
+ if (v == 0) {
+ break;
+ }
+ if ((v >= '0' && v <= '9') ||
+ (v >= 'a' && v <= 'z') ||
+ (v >= 'A' && v <= 'Z') ||
+ v == '-' ||
+ v == '_' ||
+ v == ' ' ||
+ v == '=')
+ {
+ *p_copy++ = v;
+ } else if (warned == FALSE) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Transaction name truncated. Must be only [0-9A-Za-z\\-_=]+");
+ warned = TRUE;
+ }
+ ++p_orig;
+ }
+ *p_copy++ = '*';
+ *p_copy++ = '/';
+ *p_copy++ = 0;
+ }
+ return ret;
+}
+/* }}} */
+
+
+/* {{{ mysqli_commit_or_rollback_libmysql */
+static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const unsigned int mode, const char * const name TSRMLS_DC)
+{
+ int ret;
+ smart_str tmp_str = {0, 0, 0};
+ mysqli_tx_cor_options_to_string(conn, &tmp_str, mode);
+ smart_str_0(&tmp_str);
+
+ {
+ char * query;
+ char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
+ size_t query_len;
+
+ query_len = spprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
+ name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
+ smart_str_free(&tmp_str);
+ if (name_esc) {
+ efree(name_esc);
+ name_esc = NULL;
+ }
+
+ ret = mysql_real_query(conn, query, query_len);
+ efree(query);
+ }
+ return ret;
+}
+/* }}} */
+#endif
+
+
/* {{{ proto mixed mysqli_affected_rows(object link)
Get number of affected rows in previous MySQL operation */
PHP_FUNCTION(mysqli_affected_rows)
@@ -599,10 +704,20 @@ void php_mysqli_close(MY_MYSQL * mysql, int close_type, int resource_status TSRM
#if defined(MYSQLI_USE_MYSQLND)
mysqlnd_end_psession(mysql->mysql);
#endif
- zend_ptr_stack_push(&plist->free_links, mysql->mysql);
+ if (MyG(rollback_on_cached_plink) &&
+#if !defined(MYSQLI_USE_MYSQLND)
+ mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, TRANS_COR_NO_OPT, NULL TSRMLS_CC))
+#else
+ FAIL == mysqlnd_rollback(mysql->mysql, TRANS_COR_NO_OPT, NULL))
+#endif
+ {
+ mysqli_close(mysql->mysql, close_type);
+ } else {
+ zend_ptr_stack_push(&plist->free_links, mysql->mysql);
+ MyG(num_inactive_persistent)++;
+ }
MyG(num_active_persistent)--;
- MyG(num_inactive_persistent)++;
}
}
mysql->persistent = FALSE;
@@ -637,66 +752,7 @@ PHP_FUNCTION(mysqli_close)
/* }}} */
-#if !defined(MYSQLI_USE_MYSQLND)
-/* {{{ mysqli_tx_cor_options_to_string */
-static void mysqli_tx_cor_options_to_string(const MYSQL * const conn, smart_str * str, const unsigned int mode)
-{
- if (mode & TRANS_COR_AND_CHAIN && !(mode & TRANS_COR_AND_NO_CHAIN)) {
- if (str->len) {
- smart_str_appendl(str, ", ", sizeof(", ") - 1);
- }
- smart_str_appendl(str, "AND CHAIN", sizeof("AND CHAIN") - 1);
- } else if (mode & TRANS_COR_AND_NO_CHAIN && !(mode & TRANS_COR_AND_CHAIN)) {
- if (str->len) {
- smart_str_appendl(str, ", ", sizeof(", ") - 1);
- }
- smart_str_appendl(str, "AND NO CHAIN", sizeof("AND NO CHAIN") - 1);
- }
-
- if (mode & TRANS_COR_RELEASE && !(mode & TRANS_COR_NO_RELEASE)) {
- if (str->len) {
- smart_str_appendl(str, ", ", sizeof(", ") - 1);
- }
- smart_str_appendl(str, "RELEASE", sizeof("RELEASE") - 1);
- } else if (mode & TRANS_COR_NO_RELEASE && !(mode & TRANS_COR_RELEASE)) {
- if (str->len) {
- smart_str_appendl(str, ", ", sizeof(", ") - 1);
- }
- smart_str_appendl(str, "NO RELEASE", sizeof("NO RELEASE") - 1);
- }
- smart_str_0(str);
-}
-/* }}} */
-
-
-/* {{{ proto bool mysqli_commit_or_rollback_libmysql */
-static int mysqli_commit_or_rollback_libmysql(MYSQL * conn, zend_bool commit, const unsigned int mode, const char * const name)
-{
- int ret;
- smart_str tmp_str = {0, 0, 0};
- mysqli_tx_cor_options_to_string(conn, &tmp_str, mode);
- smart_str_0(&tmp_str);
-
- {
- char * commented_name = NULL;
- unsigned int commented_name_len = name? spprintf(&commented_name, 0, " /*%s*/", name):0;
- char * query;
- unsigned int query_len = spprintf(&query, 0, (commit? "COMMIT%s %s":"ROLLBACK%s %s"),
- commented_name? commented_name:"", tmp_str.c? tmp_str.c:"");
- smart_str_free(&tmp_str);
-
- ret = mysql_real_query(conn, query, query_len);
- efree(query);
- if (commented_name) {
- efree(commented_name);
- }
- }
-}
-/* }}} */
-#endif
-
-
-/* {{{ proto bool mysqli_commit(object link)
+/* {{{ proto bool mysqli_commit(object link[, int flags [, string name ]])
Commit outstanding actions and close transaction */
PHP_FUNCTION(mysqli_commit)
{
@@ -712,7 +768,7 @@ PHP_FUNCTION(mysqli_commit)
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
#if !defined(MYSQLI_USE_MYSQLND)
- if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name)) {
+ if (mysqli_commit_or_rollback_libmysql(mysql->mysql, TRUE, flags, name TSRMLS_CC)) {
#else
if (FAIL == mysqlnd_commit(mysql->mysql, flags, name)) {
#endif
@@ -1469,7 +1525,7 @@ void php_mysqli_init(INTERNAL_FUNCTION_PARAMETERS)
We create always persistent, as if the user want to connecto
to p:somehost, we can't convert the handle then
*/
- if (!(mysql->mysql = mysql_init(TRUE)))
+ if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, TRUE)))
#endif
{
efree(mysql);
@@ -1869,6 +1925,10 @@ PHP_FUNCTION(mysqli_prepare)
efree(stmt);
RETURN_FALSE;
}
+#ifndef MYSQLI_USE_MYSQLND
+ stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
+ zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
+#endif
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->ptr = (void *)stmt;
@@ -1958,7 +2018,7 @@ PHP_FUNCTION(mysqli_rollback)
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
#if !defined(MYSQLI_USE_MYSQLND)
- if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name)) {
+ if (mysqli_commit_or_rollback_libmysql(mysql->mysql, FALSE, flags, name TSRMLS_CC)) {
#else
if (FAIL == mysqlnd_rollback(mysql->mysql, flags, name)) {
#endif
@@ -2413,6 +2473,10 @@ PHP_FUNCTION(mysqli_stmt_init)
efree(stmt);
RETURN_FALSE;
}
+#ifndef MYSQLI_USE_MYSQLND
+ stmt->link_handle = Z_OBJ_HANDLE(*mysql_link);
+ zend_objects_store_add_ref_by_handle(stmt->link_handle TSRMLS_CC);
+#endif
mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE));
mysqli_resource->status = MYSQLI_STATUS_INITIALIZED;
@@ -2541,7 +2605,7 @@ PHP_FUNCTION(mysqli_stmt_sqlstate)
}
/* }}} */
-/* {{{ proto object mysqli_store_result(object link)
+/* {{{ proto object mysqli_store_result(object link [, flags])
Buffer result set on client */
PHP_FUNCTION(mysqli_store_result)
{
@@ -2549,13 +2613,19 @@ PHP_FUNCTION(mysqli_store_result)
MYSQL_RES *result;
zval *mysql_link;
MYSQLI_RESOURCE *mysqli_resource;
+ long flags = 0;
- if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) {
+
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O|l", &mysql_link, mysqli_link_class_entry, &flags) == FAILURE) {
return;
}
MYSQLI_FETCH_RESOURCE_CONN(mysql, &mysql_link, MYSQLI_STATUS_VALID);
-
- if (!(result = mysql_store_result(mysql->mysql))) {
+#if MYSQLI_USE_MYSQLND
+ result = flags & MYSQLI_STORE_RESULT_COPY_DATA? mysqlnd_store_result_ofs(mysql->mysql) : mysqlnd_store_result(mysql->mysql);
+#else
+ result = mysql_store_result(mysql->mysql);
+#endif
+ if (!result) {
MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql);
RETURN_FALSE;
}
diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c
index 61e8e5c81e..e099fe7194 100644
--- a/ext/mysqli/mysqli_fe.c
+++ b/ext/mysqli/mysqli_fe.c
@@ -142,6 +142,17 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_rollback, 0, 0, 0)
ZEND_ARG_INFO(0, name)
ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_store_result, 0, 0, 1)
+ MYSQLI_ZEND_ARG_OBJ_INFO_LINK()
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+ZEND_BEGIN_ARG_INFO_EX(arginfo_class_store_result, 0, 0, 0)
+ ZEND_ARG_INFO(0, flags)
+ZEND_END_ARG_INFO()
+
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_change_user, 0, 0, 4)
MYSQLI_ZEND_ARG_OBJ_INFO_LINK()
ZEND_ARG_INFO(0, user)
@@ -373,6 +384,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_refresh, 0, 0, 1)
ZEND_ARG_INFO(0, options)
ZEND_END_ARG_INFO()
+ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_no_options, 0, 0, 0)
+ZEND_END_ARG_INFO()
+
/* {{{ mysqli_functions[]
*
@@ -425,6 +439,7 @@ const zend_function_entry mysqli_functions[] = {
#endif
PHP_FE(mysqli_get_client_info, arginfo_mysqli_only_link)
PHP_FE(mysqli_get_client_version, arginfo_mysqli_only_link)
+ PHP_FE(mysqli_get_links_stats, arginfo_mysqli_no_options)
PHP_FE(mysqli_get_host_info, arginfo_mysqli_only_link)
PHP_FE(mysqli_get_proto_info, arginfo_mysqli_only_link)
PHP_FE(mysqli_get_server_info, arginfo_mysqli_only_link)
@@ -494,7 +509,7 @@ const zend_function_entry mysqli_functions[] = {
PHP_FE(mysqli_sqlstate, arginfo_mysqli_only_link)
PHP_FE(mysqli_ssl_set, arginfo_mysqli_ssl_set)
PHP_FE(mysqli_stat, arginfo_mysqli_only_link)
- PHP_FE(mysqli_store_result, arginfo_mysqli_only_link)
+ PHP_FE(mysqli_store_result, arginfo_mysqli_store_result)
PHP_FE(mysqli_thread_id, arginfo_mysqli_only_link)
PHP_FE(mysqli_thread_safe, arginfo_mysqli_no_params)
PHP_FE(mysqli_use_result, arginfo_mysqli_only_link)
@@ -564,7 +579,7 @@ const zend_function_entry mysqli_link_methods[] = {
PHP_FALIAS(ssl_set, mysqli_ssl_set, arginfo_class_mysqli_ssl_set)
PHP_FALIAS(stat, mysqli_stat, arginfo_mysqli_no_params)
PHP_FALIAS(stmt_init, mysqli_stmt_init, arginfo_mysqli_no_params)
- PHP_FALIAS(store_result, mysqli_store_result, arginfo_mysqli_no_params)
+ PHP_FALIAS(store_result, mysqli_store_result, arginfo_class_store_result)
PHP_FALIAS(thread_safe, mysqli_thread_safe, arginfo_mysqli_no_params)
PHP_FALIAS(use_result, mysqli_use_result, arginfo_mysqli_no_params)
PHP_FALIAS(refresh,mysqli_refresh, arginfo_class_mysqli_refresh)
diff --git a/ext/mysqli/mysqli_fe.h b/ext/mysqli/mysqli_fe.h
index d5ae8a6ff9..9a9f851248 100644
--- a/ext/mysqli/mysqli_fe.h
+++ b/ext/mysqli/mysqli_fe.h
@@ -60,6 +60,7 @@ PHP_FUNCTION(mysqli_get_charset);
PHP_FUNCTION(mysqli_get_client_info);
PHP_FUNCTION(mysqli_get_client_version);
PHP_FUNCTION(mysqli_get_host_info);
+PHP_FUNCTION(mysqli_get_links_stats);
PHP_FUNCTION(mysqli_get_proto_info);
PHP_FUNCTION(mysqli_get_server_info);
PHP_FUNCTION(mysqli_get_server_version);
diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c
index c9e45968b3..034c835b96 100644
--- a/ext/mysqli/mysqli_nonapi.c
+++ b/ext/mysqli/mysqli_nonapi.c
@@ -217,7 +217,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
#if !defined(MYSQLI_USE_MYSQLND)
if (!(mysql->mysql = mysql_init(NULL))) {
#else
- if (!(mysql->mysql = mysqlnd_init(persistent))) {
+ if (!(mysql->mysql = mysqlnd_init(MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA, persistent))) {
#endif
goto err;
}
@@ -240,7 +240,7 @@ void mysqli_common_connect(INTERNAL_FUNCTION_PARAMETERS, zend_bool is_real_conne
if (mysql_real_connect(mysql->mysql, hostname, username, passwd, dbname, port, socket, flags) == NULL)
#else
if (mysqlnd_connect(mysql->mysql, hostname, username, passwd, passwd_len, dbname, dbname_len,
- port, socket, flags TSRMLS_CC) == NULL)
+ port, socket, flags, MYSQLND_CLIENT_KNOWS_RSET_COPY_DATA TSRMLS_CC) == NULL)
#endif
{
/* Save error messages - for mysqli_connect_error() & mysqli_connect_errno() */
@@ -575,7 +575,7 @@ PHP_FUNCTION(mysqli_query)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query");
RETURN_FALSE;
}
- if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT) {
+ if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) != MYSQLI_STORE_RESULT) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode");
RETURN_FALSE;
}
@@ -609,9 +609,14 @@ PHP_FUNCTION(mysqli_query)
RETURN_TRUE;
}
- switch (resultmode) {
+ switch (resultmode & ~(MYSQLI_ASYNC | MYSQLI_STORE_RESULT_COPY_DATA)) {
case MYSQLI_STORE_RESULT:
- result = mysql_store_result(mysql->mysql);
+#ifdef MYSQLI_USE_MYSQLND
+ if (resultmode & MYSQLI_STORE_RESULT_COPY_DATA) {
+ result = mysqlnd_store_result_ofs(mysql->mysql);
+ } else
+#endif
+ result = mysql_store_result(mysql->mysql);
break;
case MYSQLI_USE_RESULT:
result = mysql_use_result(mysql->mysql);
@@ -1046,12 +1051,14 @@ PHP_FUNCTION(mysqli_get_charset)
/* }}} */
#endif
-
#if !defined(MYSQLI_USE_MYSQLND)
+extern char * mysqli_escape_string_for_tx_name_in_comment(const char * const name TSRMLS_DC);
+
/* {{{ proto bool mysqli_begin_transaction_libmysql */
-static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name)
+static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mode, const char * const name TSRMLS_DC)
{
int ret;
+ zend_bool err = FALSE;
smart_str tmp_str = {0, 0, 0};
if (mode & TRANS_START_WITH_CONSISTENT_SNAPSHOT) {
if (tmp_str.len) {
@@ -1059,33 +1066,37 @@ static int mysqli_begin_transaction_libmysql(MYSQL * conn, const unsigned int mo
}
smart_str_appendl(&tmp_str, "WITH CONSISTENT SNAPSHOT", sizeof("WITH CONSISTENT SNAPSHOT") - 1);
}
- if (mode & TRANS_START_READ_WRITE) {
- if (tmp_str.len) {
- smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
- }
- smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
- }
- if (mode & TRANS_START_READ_ONLY) {
- if (tmp_str.len) {
- smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+ if (mode & (TRANS_START_READ_WRITE | TRANS_START_READ_ONLY)) {
+ if (mysql_get_server_version(conn) < 50605L) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "This server version doesn't support 'READ WRITE' and 'READ ONLY'. Minimum 5.6.5 is required");
+ err = TRUE;
+ } else if (mode & TRANS_START_READ_WRITE) {
+ if (tmp_str.len) {
+ smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+ }
+ smart_str_appendl(&tmp_str, "READ WRITE", sizeof("READ WRITE") - 1);
+ } else if (mode & TRANS_START_READ_ONLY) {
+ if (tmp_str.len) {
+ smart_str_appendl(&tmp_str, ", ", sizeof(", ") - 1);
+ }
+ smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
}
- smart_str_appendl(&tmp_str, "READ ONLY", sizeof("READ ONLY") - 1);
}
smart_str_0(&tmp_str);
- {
- char * commented_name = NULL;
- unsigned int commented_name_len = name? spprintf(&commented_name, 0, " /*%s*/", name):0;
+ if (err == FALSE){
+ char * name_esc = mysqli_escape_string_for_tx_name_in_comment(name TSRMLS_CC);
char * query;
unsigned int query_len = spprintf(&query, 0, "START TRANSACTION%s %s",
- commented_name? commented_name:"", tmp_str.c? tmp_str.c:"");
+ name_esc? name_esc:"", tmp_str.c? tmp_str.c:"");
+
smart_str_free(&tmp_str);
+ if (name_esc) {
+ efree(name_esc);
+ }
ret = mysql_real_query(conn, query, query_len);
efree(query);
- if (commented_name) {
- efree(commented_name);
- }
}
return ret;
}
@@ -1120,7 +1131,7 @@ PHP_FUNCTION(mysqli_begin_transaction)
}
#if !defined(MYSQLI_USE_MYSQLND)
- if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name)) {
+ if (mysqli_begin_transaction_libmysql(mysql->mysql, flags, name TSRMLS_CC)) {
RETURN_FALSE;
}
#else
@@ -1207,6 +1218,23 @@ PHP_FUNCTION(mysqli_release_savepoint)
/* }}} */
+/* {{{ proto bool mysqli_get_links_stats()
+ Returns information about open and cached links */
+PHP_FUNCTION(mysqli_get_links_stats)
+{
+ if (ZEND_NUM_ARGS()) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "no parameters expected");
+ return;
+ }
+ array_init(return_value);
+ add_assoc_long_ex(return_value, "total", sizeof("total"), MyG(num_links));
+ add_assoc_long_ex(return_value, "active_plinks", sizeof("active_plinks"), MyG(num_active_persistent));
+ add_assoc_long_ex(return_value, "cached_plinks", sizeof("cached_plinks"), MyG(num_inactive_persistent));
+}
+/* }}} */
+
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqli/mysqli_priv.h b/ext/mysqli/mysqli_priv.h
index 190572b689..e28caebf92 100644
--- a/ext/mysqli/mysqli_priv.h
+++ b/ext/mysqli/mysqli_priv.h
@@ -114,9 +114,11 @@ PHP_MYSQLI_EXPORT(zend_object_value) mysqli_objects_new(zend_class_entry * TSRML
#define MYSQLI_USE_RESULT 1
#ifdef MYSQLI_USE_MYSQLND
#define MYSQLI_ASYNC 8
+#define MYSQLI_STORE_RESULT_COPY_DATA 16
#else
/* libmysql */
#define MYSQLI_ASYNC 0
+#define MYSQLI_STORE_RESULT_OFS 0
#endif
/* for mysqli_fetch_assoc */
diff --git a/ext/mysqli/mysqli_prop.c b/ext/mysqli/mysqli_prop.c
index d11643d215..8d28e0181f 100644
--- a/ext/mysqli/mysqli_prop.c
+++ b/ext/mysqli/mysqli_prop.c
@@ -311,19 +311,21 @@ static int result_lengths_read(mysqli_object *obj, zval **retval TSRMLS_DC)
{
MYSQL_RES *p;
ulong *ret;
+ uint field_count;
MAKE_STD_ZVAL(*retval);
CHECK_STATUS(MYSQLI_STATUS_VALID);
p = (MYSQL_RES *)((MYSQLI_RESOURCE *)(obj->ptr))->ptr;
- if (!p || !p->field_count || !(ret = mysql_fetch_lengths(p))) {
+ field_count = mysql_num_fields(p);
+ if (!p || !field_count || !(ret = mysql_fetch_lengths(p))) {
ZVAL_NULL(*retval);
} else {
ulong i;
array_init(*retval);
- for (i = 0; i < p->field_count; i++) {
+ for (i = 0; i < field_count; i++) {
add_index_long(*retval, i, ret[i]);
}
}
diff --git a/ext/mysqli/mysqli_warning.c b/ext/mysqli/mysqli_warning.c
index e100319e61..7a35a7e8ce 100644
--- a/ext/mysqli/mysqli_warning.c
+++ b/ext/mysqli/mysqli_warning.c
@@ -133,7 +133,7 @@ MYSQLI_WARNING * php_get_warnings(MYSQLND_CONN_DATA * mysql TSRMLS_DC)
return NULL;
}
- result = mysql->m->use_result(mysql TSRMLS_CC);
+ result = mysql->m->use_result(mysql, 0 TSRMLS_CC);
for (;;) {
zval **entry;
diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h
index e7c02f9c9b..0f3eb64d3b 100644
--- a/ext/mysqli/php_mysqli_structs.h
+++ b/ext/mysqli/php_mysqli_structs.h
@@ -116,6 +116,10 @@ typedef struct {
BIND_BUFFER param;
BIND_BUFFER result;
char *query;
+#ifndef MYSQLI_USE_MYSQLND
+ /* used to manage refcount with libmysql (already implement in mysqlnd) */
+ zend_object_handle link_handle;
+#endif
} MY_STMT;
typedef struct {
@@ -334,6 +338,7 @@ ZEND_BEGIN_MODULE_GLOBALS(mysqli)
HashTable *report_ht;
unsigned long multi_query;
unsigned long embedded;
+ zend_bool rollback_on_cached_plink;
ZEND_END_MODULE_GLOBALS(mysqli)
diff --git a/ext/mysqli/tests/bug66043.phpt b/ext/mysqli/tests/bug66043.phpt
index d0e8b1c3d3..52e42b6177 100644
--- a/ext/mysqli/tests/bug66043.phpt
+++ b/ext/mysqli/tests/bug66043.phpt
@@ -12,7 +12,9 @@ require_once('skipifconnectfailure.inc');
--FILE--
<?php
require 'connect.inc';
-$db = new mysqli($host, $user, $passwd, 'mysql');
+if (!$db = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+}
$stmt = $db->stmt_init();
$stmt->prepare("SELECT User FROM user WHERE password=\"\"");
diff --git a/ext/mysqli/tests/bug66762.phpt b/ext/mysqli/tests/bug66762.phpt
new file mode 100644
index 0000000000..cf1309e5a2
--- /dev/null
+++ b/ext/mysqli/tests/bug66762.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #66762 mysqli@libmysql segfault in mysqli_stmt::bind_result() when link closed
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ if (!$mysqli = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Connect failed, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ }
+
+ $read_stmt = $mysqli->prepare("SELECT 1");
+
+ var_dump($read_stmt->bind_result($data));
+
+ unset($mysqli);
+ var_dump($read_stmt->bind_result($data));
+?>
+done!
+--EXPECT--
+bool(true)
+bool(true)
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_begin_transaction.phpt b/ext/mysqli/tests/mysqli_begin_transaction.phpt
new file mode 100644
index 0000000000..6c0508172f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_begin_transaction.phpt
@@ -0,0 +1,126 @@
+--TEST--
+mysqli_begin_transaction()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ /* {{{ proto bool mysqli_begin_transaction(object link, [int flags [, string name]]) */
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_begin_transaction()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_begin_transaction($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_begin_transaction($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[004] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @mysqli_begin_transaction($link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_begin_transaction($link, 0, $link)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_begin_transaction($link, 0, "mytrx", $link)))
+ printf("[007] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ printf("[009] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_autocommit($link, true)))
+ printf("[010] Cannot turn on autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* overrule autocommit */
+ if (true !== ($tmp = mysqli_begin_transaction($link)))
+ printf("[011] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_rollback($link);
+ if ($tmp !== true)
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* empty */
+ $res = mysqli_query($link, "SELECT * FROM test");
+ var_dump($res->fetch_assoc());
+
+ /* valid flags */
+ $flags = array(MYSQLI_TRANS_START_WITH_CONSISTENT_SNAPSHOT);
+
+ if (mysqli_get_server_version($link) >= 50605) {
+ $flags[] = MYSQLI_TRANS_START_READ_WRITE;
+ $flags[] = MYSQLI_TRANS_START_READ_ONLY;
+ }
+
+ /* just coverage */
+ foreach ($flags as $flag) {
+ if (!mysqli_begin_transaction($link, $flag, sprintf("flag %d", $flag))) {
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (!mysqli_query($link, 'SELECT * FROM test') || !mysqli_rollback($link)) {
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ /* does it really set a flag? */
+ if (mysqli_get_server_version($link) >= 50605) {
+ if (!mysqli_begin_transaction($link, MYSQLI_TRANS_START_READ_ONLY, sprintf("flag %d", $flag))) {
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ if (mysqli_query($link, "INSERT INTO test(id) VALUES (2)")) {
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ } else if (!mysqli_commit($link)) {
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ } else {
+ $res = mysqli_query($link, "SELECT id FROM test WHERE id = 2");
+ }
+ }
+
+ if (!mysqli_begin_transaction($link, -1)) {
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ if (mysqli_get_server_version($link) >= 50605) {
+ /* does it like stupid names? */
+ if (@!$link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "*/trick me?\n\0"))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* does it like stupid names? */
+ if (@!$link->begin_transaction(MYSQLI_TRANS_START_READ_WRITE, "az09"))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+NULL
+
+Warning: mysqli_begin_transaction(): Invalid value for parameter flags (-1) in %s on line %d
+[019] [%d]%A
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user.phpt b/ext/mysqli/tests/mysqli_change_user.phpt
index bfea423c9e..7a4530f0d5 100644
--- a/ext/mysqli/tests/mysqli_change_user.phpt
+++ b/ext/mysqli/tests/mysqli_change_user.phpt
@@ -32,79 +32,91 @@ require_once('skipifconnectfailure.inc');
printf("[006] 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_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
+ if (false !== ($tmp = @mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
printf("[007] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
- if (false !== ($tmp = mysqli_change_user($link, $user, $passwd . '_unknown_really', $db)))
- printf("[008] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[008] 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_change_user($link, $user, $passwd, $db . '_unknown_really')))
+ if (false !== ($tmp = @mysqli_change_user($link, $user, $passwd . '_unknown_really', $db)))
printf("[009] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
- if (!mysqli_query($link, 'SET @mysqli_change_user_test_var=1'))
- printf("[010] Failed to set test variable: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
-
- if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
- printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- $tmp = mysqli_fetch_assoc($res);
- mysqli_free_result($res);
- if (1 != $tmp['test_var'])
- printf("[012] Cannot set test variable\n");
-
- if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, $db)))
- printf("[013] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
-
- if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
- printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- $tmp = mysqli_fetch_assoc($res);
- mysqli_free_result($res);
-
- if (substr($tmp['user'], 0, strlen($user)) !== $user)
- printf("[015] Expecting user %s, got user() %s\n", $user, $tmp['user']);
- if ($tmp['dbname'] != $db)
- printf("[016] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[010] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
- if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
- printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
- $tmp = mysqli_fetch_assoc($res);
- mysqli_free_result($res);
- if (NULL !== $tmp['test_var'])
- printf("[019] Test variable is still set!\n");
+ if (false !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db . '_unknown_really')))
+ printf("[011] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
- printf("[020] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ printf("[012] 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_change_user($link, str_repeat('user', 16384), str_repeat('pass', 16384), str_repeat('dbase', 16384))))
- printf("[021] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+ if (false !== ($tmp = @mysqli_change_user($link, str_repeat('user', 16384), str_repeat('pass', 16384), str_repeat('dbase', 16384))))
+ printf("[013] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
mysqli_close($link);
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
- printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ printf("[014] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
/* silent protocol change if no db which requires workaround in mysqlnd/libmysql
(empty db = no db send with COM_CHANGE_USER) */
if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, "")))
- printf("[023] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+ printf("[015] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
- printf("[024] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ printf("[016] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
$tmp = mysqli_fetch_assoc($res);
mysqli_free_result($res);
if ($tmp['dbname'] != "")
- printf("[025] Expecting database '', got database() '%s'\n", $tmp['dbname']);
+ printf("[017] Expecting database '', got database() '%s'\n", $tmp['dbname']);
mysqli_close($link);
if (NULL !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db)))
- printf("[026] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[019] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!mysqli_query($link, 'SET @mysqli_change_user_test_var=1'))
+ printf("[020] Failed to set test variable: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (1 != $tmp['test_var'])
+ printf("[022] Cannot set test variable\n");
+
+ if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, $db)))
+ printf("[023] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
+ printf("[024] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if (substr($tmp['user'], 0, strlen($user)) !== $user)
+ printf("[025] Expecting user %s, got user() %s\n", $user, $tmp['user']);
+ if ($tmp['dbname'] != $db)
+ printf("[026] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
+
+ if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[027] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (NULL !== $tmp['test_var'])
+ printf("[028] Test variable is still set!\n");
print "done!";
?>
diff --git a/ext/mysqli/tests/mysqli_change_user_new.phpt b/ext/mysqli/tests/mysqli_change_user_new.phpt
new file mode 100644
index 0000000000..a87afa84a3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_new.phpt
@@ -0,0 +1,44 @@
+--TEST--
+mysqli_change_user(), MySQL 5.6+
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+
+if (mysqli_get_server_version($link) < 50600)
+ die("SKIP For MySQL >= 5.6.0");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ /* Pre 5.6: link remains useable */
+ if (false !== ($tmp = @mysqli_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
+ printf("[002] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT 1 AS _one'))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($res->fetch_assoc());
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_query(): MySQL server has gone away in %s on line %d
+
+Warning: mysqli_query(): Error reading result set's header in %s on line %d
+[003] [2006] MySQL server has gone away
+
+Fatal error: Call to a member function fetch_assoc() on a non-object in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_old.phpt b/ext/mysqli/tests/mysqli_change_user_old.phpt
new file mode 100644
index 0000000000..ddb49cd189
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_change_user_old.phpt
@@ -0,0 +1,119 @@
+--TEST--
+mysqli_change_user(), MySQL < 5.6
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+
+if (mysqli_get_server_version($link) >= 50600)
+ die("SKIP For MySQL < 5.6.0");
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_change_user()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link, $link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_change_user($link, $link, $link, $link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[006] 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_change_user($link, $user . '_unknown_really', $passwd . 'non_empty', $db)))
+ printf("[007] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_change_user($link, $user, $passwd . '_unknown_really', $db)))
+ printf("[008] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_change_user($link, $user, $passwd, $db . '_unknown_really')))
+ printf("[009] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'SET @mysqli_change_user_test_var=1'))
+ printf("[010] Failed to set test variable: [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (1 != $tmp['test_var'])
+ printf("[012] Cannot set test variable\n");
+
+ if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, $db)))
+ printf("[013] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if (substr($tmp['user'], 0, strlen($user)) !== $user)
+ printf("[015] Expecting user %s, got user() %s\n", $user, $tmp['user']);
+ if ($tmp['dbname'] != $db)
+ printf("[016] Expecting database %s, got database() %s\n", $db, $tmp['dbname']);
+
+ if (!$res = mysqli_query($link, 'SELECT @mysqli_change_user_test_var AS test_var'))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (NULL !== $tmp['test_var'])
+ printf("[019] Test variable is still set!\n");
+
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[020] 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_change_user($link, str_repeat('user', 16384), str_repeat('pass', 16384), str_repeat('dbase', 16384))))
+ printf("[021] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ /* silent protocol change if no db which requires workaround in mysqlnd/libmysql
+ (empty db = no db send with COM_CHANGE_USER) */
+ if (true !== ($tmp = mysqli_change_user($link, $user, $passwd, "")))
+ printf("[023] Expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT database() AS dbname, user() AS user'))
+ printf("[024] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+
+ if ($tmp['dbname'] != "")
+ printf("[025] Expecting database '', got database() '%s'\n", $tmp['dbname']);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = @mysqli_change_user($link, $user, $passwd, $db)))
+ printf("[026] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_change_user_oo.phpt b/ext/mysqli/tests/mysqli_change_user_oo.phpt
index 61444ae235..7ed2d08933 100644
--- a/ext/mysqli/tests/mysqli_change_user_oo.phpt
+++ b/ext/mysqli/tests/mysqli_change_user_oo.phpt
@@ -10,6 +10,9 @@ require_once('table.inc');
if (!$IS_MYSQLND && (mysqli_get_server_version($link) < 50118 && mysqli_get_server_version($link) > 50100)) {
die("skip Your MySQL Server version has a known bug that will cause a crash");
}
+
+if (mysqli_get_server_version($link) >= 50600)
+ die("SKIP For MySQL < 5.6.0");
?>
--FILE--
<?php
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
index 63ec7ca3c0..8f6c24900a 100644
--- a/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
+++ b/ext/mysqli/tests/mysqli_class_mysqli_reflection.phpt
@@ -1140,9 +1140,16 @@ isInternal: yes
isUserDefined: no
returnsReference: no
Modifiers: 256
-Number of Parameters: 0
+Number of Parameters: 1
Number of Required Parameters: 0
+Inspecting parameter 'flags' of method 'store_result'
+isArray: no
+allowsNull: no
+isPassedByReference: no
+isOptional: yes
+isDefaultValueAvailable: no
+
Inspecting method 'thread_safe'
isFinal: no
isAbstract: no
diff --git a/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt b/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
index 988b82732a..95400e43e0 100644
--- a/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
+++ b/ext/mysqli/tests/mysqli_class_mysqli_result_reflection.phpt
@@ -233,7 +233,7 @@ isDestructor: no
isInternal: yes
isUserDefined: no
returnsReference: no
-Modifiers: 256
+Modifiers: 268435712
Number of Parameters: 2
Number of Required Parameters: 0
@@ -366,4 +366,4 @@ Default property 'field_count'
Default property 'lengths'
Default property 'num_rows'
Default property 'type'
-done! \ No newline at end of file
+done!
diff --git a/ext/mysqli/tests/mysqli_commit_oo.phpt b/ext/mysqli/tests/mysqli_commit_oo.phpt
index e19f698e81..77bcf412e7 100644
--- a/ext/mysqli/tests/mysqli_commit_oo.phpt
+++ b/ext/mysqli/tests/mysqli_commit_oo.phpt
@@ -21,49 +21,78 @@ if (!have_innodb($link))
$link = NULL;
$mysqli = new mysqli();
- if (!is_null($tmp = @$mysqli->commit()))
+ if (!is_null($tmp = @$mysqli->commit())) {
printf("[013] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+ }
- if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket))
+ if (!$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket)) {
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
+ }
- if (true !== ($tmp = $mysqli->commit()))
+ if (true !== ($tmp = $mysqli->commit())) {
printf("[002] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+ }
- if (true !== ($tmp = $mysqli->autocommit(false)))
+ if (true !== ($tmp = $mysqli->autocommit(false))) {
printf("[003] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+ }
- if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ if (!$mysqli->query('DROP TABLE IF EXISTS test')) {
printf("[004] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
- if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ if (!$mysqli->query('CREATE TABLE test(id INT) ENGINE = InnoDB')) {
printf("[005] Cannot create test table, [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
- if (!$mysqli->query('INSERT INTO test(id) VALUES (1)'))
+ if (!$mysqli->query('INSERT INTO test(id) VALUES (1)')) {
printf("[006] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
$tmp = $mysqli->commit();
- if ($tmp !== true)
+ if ($tmp !== true) {
printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ }
if (!$mysqli->query('ROLLBACK'))
printf("[008] [%d] %s\n", $mysqli->errno, $mysqli->error);
- if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test'))
+ if (!$res = $mysqli->query('SELECT COUNT(*) AS num FROM test')) {
printf("[009] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
$tmp = $res->fetch_assoc();
- if (1 != $tmp['num'])
+ if (1 != $tmp['num']) {
printf("[010] Expecting 1 row in table test, found %d rows\n", $tmp['num']);
+ }
$res->free();
- if (!$mysqli->query('DROP TABLE IF EXISTS test'))
+ if (!$mysqli->query('DROP TABLE IF EXISTS test')) {
printf("[011] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+
+ if (!$mysqli->commit(0 , "tx_name0123")) {
+ printf("[012] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+ if (!$mysqli->commit(0 , "*/ nonsense")) {
+ printf("[013] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+ if (!$mysqli->commit(0 , "tx_name ulf вендел")) {
+ printf("[014] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+ if (!$mysqli->commit(0 , "tx_name \t\n\r\b")) {
+ printf("[015] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
+ if (!$mysqli->commit(MYSQLI_TRANS_COR_AND_CHAIN | MYSQLI_TRANS_COR_NO_RELEASE , "tx_name")) {
+ printf("[016] [%d] %s\n", $mysqli->errno, $mysqli->error);
+ }
$mysqli->close();
- if (NULL !== ($tmp = @$mysqli->commit()))
- printf("[012] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ if (NULL !== ($tmp = @$mysqli->commit())) {
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ }
print "done!";
?>
@@ -72,4 +101,9 @@ if (!have_innodb($link))
require_once("clean_table.inc");
?>
--EXPECTF--
+Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d
+
+Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d
+
+Warning: mysqli::commit(): Transaction name truncated. Must be only [0-9A-Za-z\-_=]+ in %s on line %d
done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_constants.phpt b/ext/mysqli/tests/mysqli_constants.phpt
index 7c6dacd393..bed9d53419 100644
--- a/ext/mysqli/tests/mysqli_constants.phpt
+++ b/ext/mysqli/tests/mysqli_constants.phpt
@@ -108,6 +108,10 @@ require_once('skipifconnectfailure.inc');
$expected_constants['MYSQLI_OPT_INT_AND_FLOAT_NATIVE'] = true;
}
+ if ($IS_MYSQLND && defined('MYSQLI_STORE_RESULT_COPY_DATA')) {
+ $expected_constants['MYSQLI_STORE_RESULT_COPY_DATA'] = true;
+ }
+
if ($IS_MYSQLND || defined('MYSQLI_REFRESH_BACKUP_LOG')) {
$expected_constants['MYSQLI_REFRESH_BACKUP_LOG'] = true;
}
diff --git a/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt b/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
index 8ecf516cad..257926bae9 100644
--- a/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
+++ b/ext/mysqli/tests/mysqli_debug_mysqlnd_only.phpt
@@ -90,9 +90,9 @@ if (!$IS_MYSQLND)
if (isset($functions_trace[$name]))
$found++;
- if ($found < (count($memory_funcs) - 2))
+ if ($found < (count($memory_funcs) - 3))
printf("[016] Only %d memory functions have been found, expecting at least %d.\n",
- $found, count($memory_funcs) - 2);
+ $found, count($memory_funcs) - 3);
$trace = try_control_string($link, 't:O,' . $trace_file, $trace_file, 20);
if (!strstr($trace, 'SELECT * FROM test') && !strstr($trace, 'mysql_real_query'))
diff --git a/ext/mysqli/tests/mysqli_fetch_all.phpt b/ext/mysqli/tests/mysqli_fetch_all.phpt
index 63b6ad2848..854b8160f0 100644
--- a/ext/mysqli/tests/mysqli_fetch_all.phpt
+++ b/ext/mysqli/tests/mysqli_fetch_all.phpt
@@ -299,6 +299,26 @@ if (!function_exists('mysqli_fetch_all'))
if (null !== ($tmp = mysqli_fetch_array($res, MYSQLI_ASSOC)))
printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[016] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!$res = mysqli_real_query($link, "SELECT 1 AS _one"))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* on mysqlnd level this would not be allowed */
+ if (!is_object($res = mysqli_use_result($link)))
+ printf("[018] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ $rows = mysqli_fetch_all($res, MYSQLI_ASSOC);
+ if (!is_array($rows) || (count($rows) > 1) || !isset($rows[0]['_one']) || ($rows[0]['_one'] != 1)) {
+ printf("[019] Results seem wrong, dumping\n");
+ var_dump($rows);
+ }
+
+
print "done!";
?>
--CLEAN--
diff --git a/ext/mysqli/tests/mysqli_fetch_lengths.phpt b/ext/mysqli/tests/mysqli_fetch_lengths.phpt
index 1abc61170e..6d0b698ee7 100644
--- a/ext/mysqli/tests/mysqli_fetch_lengths.phpt
+++ b/ext/mysqli/tests/mysqli_fetch_lengths.phpt
@@ -10,8 +10,10 @@ require_once('skipifconnectfailure.inc');
<?php
require_once("connect.inc");
- if (!$mysqli = new mysqli($host, $user, $passwd, $db, $port, $socket))
- printf("[001] Cannot connect\n");
+ if (!$mysqli = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
if (!is_null($tmp = @mysqli_fetch_lengths()))
printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
diff --git a/ext/mysqli/tests/mysqli_pconn_max_links.phpt b/ext/mysqli/tests/mysqli_pconn_max_links.phpt
index e87ef00b21..99e51e7c5e 100644
--- a/ext/mysqli/tests/mysqli_pconn_max_links.phpt
+++ b/ext/mysqli/tests/mysqli_pconn_max_links.phpt
@@ -42,6 +42,7 @@ Persistent connections and mysqli.max_links
--INI--
mysqli.allow_persistent=1
mysqli.max_persistent=2
+mysqli.rollback_on_cached_plink=1
--FILE--
<?php
require_once("connect.inc");
@@ -58,10 +59,18 @@ mysqli.max_persistent=2
mysqli_errno($plink), mysqli_error($plink));
}
+ var_dump(mysqli_get_links_stats(1));
+
+ echo "Before pconnect:";
+ var_dump(mysqli_get_links_stats());
+
if (!$plink = my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
printf("[001] Cannot connect using the second DB user created during SKIPIF, [%d] %s\n",
mysqli_connect_errno(), mysqli_connect_error());
+ echo "After pconnect:";
+ var_dump(mysqli_get_links_stats());
+
ob_start();
phpinfo();
$phpinfo = strip_tags(ob_get_contents());
@@ -110,11 +119,17 @@ mysqli.max_persistent=2
if (isset($running_threads[$pthread_id]))
printf("[009] Persistent connection has not been killed\n");
+ echo "Before second pconnect:";
+ var_dump(mysqli_get_links_stats());
+
// this fails and we have 0 (<= $num_plinks) connections
if ($plink = @my_mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
printf("[010] Can connect using the old password, [%d] %s\n",
mysqli_connect_errno($link), mysqli_connect_error($link));
+ echo "After second pconnect:";
+ var_dump(mysqli_get_links_stats());
+
ob_start();
phpinfo();
$phpinfo = strip_tags(ob_get_contents());
@@ -123,7 +138,13 @@ mysqli.max_persistent=2
if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
printf("[010] Cannot get # of active persistent links from phpinfo()\n");
+ var_dump(mysqli_get_links_stats());
+
$num_plinks_kill = $matches[1];
+ $sstats = mysqli_get_links_stats();
+ if ($sstats['active_plinks'] != $num_plinks_kill) {
+ printf("[010.2] Num of active plinks differ %s %s\n", $sstats['active_plinks'], $num_plinks_kill);
+ }
if ($num_plinks_kill > $num_plinks)
printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill);
@@ -141,9 +162,11 @@ mysqli.max_persistent=2
mysqli_free_result($res);
var_dump($row);
- if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket))
+ if ($plink2 = my_mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket)) {
printf("[015] Can open more persistent connections than allowed, [%d] %s\n",
mysqli_connect_errno(), mysqli_connect_error());
+ var_dump(mysqli_get_links_stats());
+ }
ob_start();
phpinfo();
@@ -179,18 +202,71 @@ mysqli_query($link, 'DROP USER pcontest');
mysqli_close($link);
?>
--EXPECTF--
-array(2) {
- [%u|b%"id"]=>
- %unicode|string%(1) "1"
- [%u|b%"label"]=>
- %unicode|string%(1) "a"
+Warning: mysqli_get_links_stats(): no parameters expected in %s on line %d
+NULL
+Before pconnect:array(3) {
+ ["total"]=>
+ int(1)
+ ["active_plinks"]=>
+ int(0)
+ ["cached_plinks"]=>
+ int(0)
+}
+After pconnect:array(3) {
+ ["total"]=>
+ int(2)
+ ["active_plinks"]=>
+ int(1)
+ ["cached_plinks"]=>
+ int(0)
}
array(2) {
- [%u|b%"id"]=>
- %unicode|string%(1) "1"
- [%u|b%"label"]=>
- %unicode|string%(1) "a"
+ ["id"]=>
+ string(1) "1"
+ ["label"]=>
+ string(1) "a"
+}
+Before second pconnect:array(3) {
+ ["total"]=>
+ int(2)
+ ["active_plinks"]=>
+ int(1)
+ ["cached_plinks"]=>
+ int(0)
}
-Warning: %s: Too many open persistent links (%d) in %s on line %d
+Warning: main(): MySQL server has gone away in %s on line %d
+
+Warning: main(): Error reading result set's header in %s line %d
+After second pconnect:array(3) {
+ ["total"]=>
+ int(1)
+ ["active_plinks"]=>
+ int(0)
+ ["cached_plinks"]=>
+ int(0)
+}
+array(3) {
+ ["total"]=>
+ int(1)
+ ["active_plinks"]=>
+ int(0)
+ ["cached_plinks"]=>
+ int(0)
+}
+array(2) {
+ ["id"]=>
+ string(1) "1"
+ ["label"]=>
+ string(1) "a"
+}
+[015] Can open more persistent connections than allowed, [0]
+array(3) {
+ ["total"]=>
+ int(3)
+ ["active_plinks"]=>
+ int(2)
+ ["cached_plinks"]=>
+ int(0)
+}
done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_poll.phpt b/ext/mysqli/tests/mysqli_poll.phpt
index dd4f9b9710..8a49ba3f82 100644
--- a/ext/mysqli/tests/mysqli_poll.phpt
+++ b/ext/mysqli/tests/mysqli_poll.phpt
@@ -52,6 +52,13 @@ if (!$IS_MYSQLND)
if (0 !== ($tmp = (mysqli_poll($read, $error, $reject, 0, 1))))
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));
function poll_async($offset, $link, $links, $errors, $reject, $exp_ready, $use_oo_syntax) {
@@ -90,14 +97,14 @@ if (!$IS_MYSQLND)
$links = array($link);
$errors = array($link);
$reject = array($link);
- poll_async(10, $link, $links, $errors, $reject, 0, false);
+ poll_async(12, $link, $links, $errors, $reject, 0, false);
mysqli_close($link);
$link = get_connection();
$links = array($link);
$errors = array($link);
$reject = array($link);
- poll_async(11, $link, $links, $errors, $reject, 0, true);
+ poll_async(13, $link, $links, $errors, $reject, 0, true);
mysqli_close($link);
// Connections on which no query has been send - 2
@@ -106,7 +113,7 @@ if (!$IS_MYSQLND)
$links = array($link, $link);
$errors = array($link, $link);
$reject = array();
- poll_async(12, $link, $links, $errors, $reject, 0, false);
+ poll_async(14, $link, $links, $errors, $reject, 0, false);
// Connections on which no query has been send - 3
// Difference: pass two connections
@@ -114,7 +121,7 @@ if (!$IS_MYSQLND)
$links = array($link, get_connection());
$errors = array($link, $link);
$reject = array();
- poll_async(13, $link, $links, $errors, $reject, 0, false);
+ poll_async(15, $link, $links, $errors, $reject, 0, false);
// Reference mess...
$link = get_connection();
@@ -122,16 +129,20 @@ if (!$IS_MYSQLND)
$errors = array($link);
$ref_errors =& $errors;
$reject = array();
- poll_async(14, $link, $links, $ref_errors, $reject, 0, false);
+ poll_async(16, $link, $links, $ref_errors, $reject, 0, false);
print "done!";
?>
--EXPECTF--
-[010 + 6] Rejecting thread %d: 0/
-[011 + 6] Rejecting thread %d: 0/
-[012 + 6] Rejecting thread %d: 0/
+
+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
[012 + 6] Rejecting thread %d: 0/
[013 + 6] Rejecting thread %d: 0/
-[013 + 6] Rejecting thread %d: 0/
[014 + 6] Rejecting thread %d: 0/
-done!
+[014 + 6] Rejecting thread %d: 0/
+[015 + 6] Rejecting thread %d: 0/
+[015 + 6] Rejecting thread %d: 0/
+[016 + 6] Rejecting thread %d: 0/
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_poll_kill.phpt b/ext/mysqli/tests/mysqli_poll_kill.phpt
index b068d64e8f..c69a251111 100644
--- a/ext/mysqli/tests/mysqli_poll_kill.phpt
+++ b/ext/mysqli/tests/mysqli_poll_kill.phpt
@@ -90,6 +90,7 @@ if (!$IS_MYSQLND)
// Yes, 1 - fetch OK packet of kill!
$processed = 0;
+ $begin = microtime(true);
do {
$links = array($link, $link);
$errors = array($link, $link);
@@ -106,9 +107,14 @@ if (!$IS_MYSQLND)
break;
}
+ if (FALSE === $ready) {
+ printf("[013] MySQLi indicates some error\n");
+ break;
+ }
+
if (!empty($reject)) {
foreach ($reject as $mysqli) {
- printf("[013] Rejecting thread %d: %s/%s\n",
+ printf("[014] Rejecting thread %d: %s/%s\n",
mysqli_thread_id($mysqli),
mysqli_errno($mysqli),
mysqli_error($mysqli));
@@ -121,11 +127,16 @@ if (!$IS_MYSQLND)
printf("Fetching from thread %d...\n", mysqli_thread_id($mysqli));
var_dump(mysqli_fetch_assoc($res));
} else if (mysqli_errno($mysqli) > 0) {
- printf("[014] %d/%s\n", mysqli_errno($mysqli), mysqli_error($mysqli));
+ printf("[015] %d/%s\n", mysqli_errno($mysqli), mysqli_error($mysqli));
}
$processed++;
}
+ if ((microtime(true) - $begin) > 5) {
+ printf("[016] Pulling the emergency break after 5s, something is wrong...\n");
+ break;
+ }
+
} while ($processed < 2);
@@ -137,17 +148,17 @@ if (!$IS_MYSQLND)
// Sleep 0.1s to ensure the KILL gets recognized
usleep(100000);
if (false !== ($tmp = mysqli_query($link, "SELECT 1 AS 'processed before killed'", MYSQLI_ASYNC | MYSQLI_USE_RESULT)))
- printf("[015] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
+ printf("[017] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true));
$links = array($link);
$errors = array($link);
$reject = array($link);
if (0 !== ($tmp = (mysqli_poll($links, $errors, $reject, 0, 10000))))
- printf("[016] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
+ printf("[018] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true));
if (!is_array($links) || empty($links))
- printf("[017] Expecting non-empty array got %s/%s\n", gettype($links), var_export($links, true));
+ printf("[019] Expecting non-empty array got %s/%s\n", gettype($links), var_export($links, true));
else
foreach ($links as $link) {
if (is_object($res = mysqli_reap_async_query($link))) {
@@ -156,16 +167,16 @@ if (!$IS_MYSQLND)
mysqli_free_result($res);
} else if ($link->errno > 0) {
// But you are supposed to handle the error the way its shown here!
- printf("[018] Error: %d/%s\n", $link->errno, $link->error);
+ printf("[020] Error: %d/%s\n", $link->errno, $link->error);
}
}
// None of these will indicate an error, check errno on the list of returned connections!
if (!is_array($errors) || !empty($errors))
- printf("[019] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true));
+ printf("[021] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true));
if (!is_array($reject) || !empty($reject))
- printf("[020] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true));
+ printf("[021] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true));
mysqli_close($link);
diff --git a/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt b/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt
index 9c02cf9760..9068f6f708 100644
--- a/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt
+++ b/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt
@@ -80,13 +80,17 @@ if (!$IS_MYSQLND)
if (0 == count($poll_links))
break;
- if (0 == ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000)))
+ if (0 === ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000)))
continue;
if (!empty($poll_errors)) {
die(var_dump($poll_errors));
}
+ if (FALSE === $num_ready) {
+ die("Some mysqli indicated error");
+ }
+
foreach ($poll_links as $link) {
$thread_id = mysqli_thread_id($link);
$links[$thread_id]['processed'] = true;
diff --git a/ext/mysqli/tests/mysqli_reap_async_query.phpt b/ext/mysqli/tests/mysqli_reap_async_query.phpt
new file mode 100644
index 0000000000..e3858e6172
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_reap_async_query.phpt
@@ -0,0 +1,97 @@
+--TEST--
+mysqli_reap_async_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$IS_MYSQLND)
+ die("skip mysqlnd only feature, compile PHP using --with-mysqli=mysqlnd");
+?>
+--FILE--
+<?php
+ require_once('connect.inc');
+
+ function get_connection() {
+ global $host, $user, $passwd, $db, $port, $socket;
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+ return $link;
+ }
+
+ if (!$link = get_connection())
+ printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (NULL !== ($tmp = @mysqli_reap_async_query()))
+ printf("[002] Expecting NULL got %s\n", var_export($tmp, true));
+
+ $l = array($link);
+ if (NULL !== ($tmp = @mysqli_reap_async_query($l)))
+ printf("[003] Expecting NULL got %s\n", var_export($tmp, true));
+
+ if (NULL !== ($tmp = @mysqli_reap_async_query($link, $link)))
+ printf("[004] Expecting NULL got %s\n", var_export($tmp, true));
+
+
+ function poll_async($offset, $link, $links, $errors, $reject, $exp_ready, $use_oo_syntax) {
+
+ if ($exp_ready !== ($tmp = mysqli_poll($links, $errors, $reject, 0, 1000)))
+ printf("[%03d + 1] There should be %d links ready to read from, %d ready\n",
+ $offset, $exp_ready, $tmp);
+
+ foreach ($links as $mysqli) {
+ if ($use_oo_syntax) {
+ $res = $mysqli->reap_async_query();
+ } else {
+ $res = mysqli_reap_async_query($mysqli);
+ }
+ if (is_object($res)) {
+ printf("[%03d + 2] %s\n", $offset, var_export($res->fetch_assoc(), true));
+ } else if (mysqli_errno($mysqli) > 0) {
+ printf("[%03d + 3] Error indicated through links array: %d/%s",
+ $offset, mysqli_errno($mysqli), mysqli_error($mysqli));
+ } else {
+ printf("[%03d + 4] Cannot fetch and no error set - non resultset query (no SELECT)!\n", $offset);
+ }
+ }
+
+ foreach ($errors as $mysqli)
+ printf("[%03d + 5] Error on %d: %d/%s\n",
+ $offset, mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli));
+
+ foreach ($reject as $mysqli)
+ printf("[%03d + 6] Rejecting thread %d: %d/%s\n",
+ $offset, mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli));
+
+ }
+
+ // Connections on which no query has been send - 1
+ $link = get_connection();
+ $link->query("SELECT 1 AS _one", MYSQLI_ASYNC | MYSQLI_STORE_RESULT);
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+ poll_async(12, $link, $links, $errors, $reject, 1, false);
+ mysqli_close($link);
+
+ $link = get_connection();
+ $link->query("SELECT 2 AS _two", MYSQLI_ASYNC | MYSQLI_USE_RESULT);
+ $links = array($link);
+ $errors = array($link);
+ $reject = array($link);
+ poll_async(13, $link, $links, $errors, $reject, 1, true);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+[012 + 2] array (
+ '_one' => '1',
+)
+[013 + 2] array (
+ '_two' => '2',
+)
+done!
diff --git a/ext/mysqli/tests/mysqli_release_savepoint.phpt b/ext/mysqli/tests/mysqli_release_savepoint.phpt
new file mode 100644
index 0000000000..ba4c564385
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_release_savepoint.phpt
@@ -0,0 +1,84 @@
+--TEST--
+mysqli_release_savepoint()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ /* {{{ proto bool mysqli_release_savepoint(object link, string name) */
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_release_savepoint()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_release_savepoint($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ 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);
+
+ $name = array();
+ if (!is_null($tmp = @mysqli_release_savepoint($link, $name)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_release_savepoint($link, 'foo', $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_release_savepoint($link, '')))
+ printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ printf("[008] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_autocommit($link, false)))
+ printf("[009] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* note that there is no savepoint my... */
+ if (true !== ($tmp = mysqli_release_savepoint($link, 'my')))
+ printf("[010] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_commit($link);
+ if ($tmp !== true)
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_savepoint($link, 'my')))
+ printf("[013] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
+
+ $res = mysqli_query($link, "SELECT * FROM test");
+ var_dump($res->fetch_assoc());
+
+ if (true !== ($tmp = mysqli_release_savepoint($link, 'my')))
+ printf("[014] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+Warning: mysqli_release_savepoint(): Savepoint name cannot be empty in %s on line %d
+array(1) {
+ ["id"]=>
+ string(1) "1"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_report.phpt b/ext/mysqli/tests/mysqli_report.phpt
index f5d77e38bc..4d2d3553d1 100644
--- a/ext/mysqli/tests/mysqli_report.phpt
+++ b/ext/mysqli/tests/mysqli_report.phpt
@@ -43,8 +43,6 @@ require_once('skipifconnectfailure.inc');
mysqli_multi_query($link, "BAR; FOO;");
mysqli_query($link, "FOO");
- /* This might work if you accept anonymous users in your setup */
- mysqli_change_user($link, "0123456789-10-456789-20-456789-30-456789-40-456789-50-456789-60-456789-70-456789-80-456789-90-456789", "password", $db);
mysqli_kill($link, -1);
// mysqli_ping() cannot be tested, because one would need to cause an error inside the C function to test it
@@ -61,7 +59,6 @@ require_once('skipifconnectfailure.inc');
mysqli_multi_query($link, "BAR; FOO;");
mysqli_query($link, "FOO");
- mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db);
mysqli_kill($link, -1);
mysqli_prepare($link, "FOO");
mysqli_real_query($link, "FOO");
@@ -291,8 +288,6 @@ Warning: mysqli_multi_query(): (%d/%d): You have an error in your SQL syntax; ch
Warning: mysqli_query(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
-Warning: mysqli_change_user(): (%d/%d): Access denied for user '%s'@'%s' (using password: %s) in %s on line %d
-
Warning: mysqli_kill(): processid should have positive value in %s on line %d
Warning: mysqli_prepare(): (%d/%d): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FOO' at line 1 in %s on line %d
diff --git a/ext/mysqli/tests/mysqli_report_new.phpt b/ext/mysqli/tests/mysqli_report_new.phpt
new file mode 100644
index 0000000000..5cf5ca8e3b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_report_new.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_report(), change user, MySQL 5.6+
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+
+if (mysqli_get_server_version($link) < 50600)
+ die("SKIP For MySQL >= 5.6.0");
+
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+
+ /*
+ Internal macro MYSQL_REPORT_ERROR
+ */
+ mysqli_report(MYSQLI_REPORT_ERROR);
+
+ mysqli_change_user($link, "0123456789-10-456789-20-456789-30-456789-40-456789-50-456789-60-456789-70-456789-80-456789-90-456789", "password", $db);
+
+ mysqli_report(MYSQLI_REPORT_OFF);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ mysqli_change_user($link, "This might work if you accept anonymous users in your setup", "password", $db);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+
+Warning: mysqli_change_user(): (%d/%d): Access denied for user '%s'@'%s' (using password: %s) in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_report_wo_ps.phpt b/ext/mysqli/tests/mysqli_report_wo_ps.phpt
index cc57511b5b..dae81b21cc 100644
--- a/ext/mysqli/tests/mysqli_report_wo_ps.phpt
+++ b/ext/mysqli/tests/mysqli_report_wo_ps.phpt
@@ -1,10 +1,17 @@
--TEST--
-mysqli_report()
+mysqli_report(), MySQL < 5.6
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifemb.inc');
require_once('skipifconnectfailure.inc');
+
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("SKIP Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket));
+
+if (mysqli_get_server_version($link) >= 50600)
+ die("SKIP For MySQL < 5.6.0");
?>
--FILE--
<?php
diff --git a/ext/mysqli/tests/mysqli_savepoint.phpt b/ext/mysqli/tests/mysqli_savepoint.phpt
new file mode 100644
index 0000000000..5775b0eaec
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_savepoint.phpt
@@ -0,0 +1,72 @@
+--TEST--
+mysqli_savepoint()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+require_once('connect.inc');
+if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!have_innodb($link))
+ die(sprintf("Needs InnoDB support, [%d] %s", $link->errno, $link->error));
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+ /* {{{ proto bool mysqli_savepoint(object link, string name) */
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_savepoint()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_savepoint($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ 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);
+
+ $name = array();
+ if (!is_null($tmp = @mysqli_savepoint($link, $name)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_savepoint($link, 'foo', $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_savepoint($link, '')))
+ printf("[006] Expecting false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'DROP TABLE IF EXISTS test'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'CREATE TABLE test(id INT) ENGINE = InnoDB'))
+ printf("[008] Cannot create test table, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_autocommit($link, false)))
+ printf("[009] Cannot turn off autocommit, expecting true, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* overrule autocommit */
+ if (true !== ($tmp = mysqli_savepoint($link, 'my')))
+ printf("[010] Got %s - [%d] %s\n", var_dump($tmp, true), mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'INSERT INTO test(id) VALUES (1)'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $tmp = mysqli_rollback($link);
+ if ($tmp !== true)
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+
+Warning: mysqli_savepoint(): Savepoint name cannot be empty in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt b/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
index 2b0e150ded..69755865e9 100644
--- a/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
+++ b/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
@@ -17,7 +17,7 @@ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
!mysqli_query($link, "CREATE TABLE test(id SMALLINT)"))
die(sprintf("skip [%d] %s\n", $link->errno, $link->error));
-if (!@mysqli_query("INSERT INTO test(id) VALUES (100001)"))
+if (!@mysqli_query($link, "SET sql_mode=''") || !@mysqli_query($link, "INSERT INTO test(id) VALUES (100001)"))
die("skip Strict sql mode seems to be active. We won't get a warning to check for.");
mysqli_query($link, "DROP TABLE IF EXISTS test");
@@ -43,54 +43,57 @@ mysqli_query($link, "DROP TABLE IF EXISTS test");
if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
- if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") || !mysqli_stmt_execute($stmt))
+ if (!mysqli_stmt_prepare($stmt, "SET sql_mode=''") || !mysqli_stmt_execute($stmt))
printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") || !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
- printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_stmt_prepare($stmt, "CREATE TABLE test(id SMALLINT, label CHAR(1))") || !mysqli_stmt_execute($stmt))
- printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
- printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100000, 'a'), (100001, 'b')") ||
!mysqli_stmt_execute($stmt))
- printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
if (!is_object($warning = mysqli_stmt_get_warnings($stmt)))
- printf("[010] Expecting mysqli_warning object, got %s/%s\n", gettype($warning), $warning);
+ printf("[011] Expecting mysqli_warning object, got %s/%s\n", gettype($warning), $warning);
if ('mysqli_warning' !== get_class($warning))
- printf("[011] Expecting object of type mysqli_warning got type '%s'", get_class($warning));
+ printf("[012] Expecting object of type mysqli_warning got type '%s'", get_class($warning));
if (!method_exists($warning, 'next'))
- printf("[012] Object mysqli_warning seems to lack method next()\n");
+ printf("[013] Object mysqli_warning seems to lack method next()\n");
$i = 0;
do {
if ('' == $warning->message)
- printf("[013 - %d] Message should not be empty\n", $i);
+ printf("[014 - %d] Message should not be empty\n", $i);
if ('' == $warning->sqlstate)
- printf("[014 - %d] SQL State should not be empty\n", $i);
+ printf("[015 - %d] SQL State should not be empty\n", $i);
if (0 == $warning->errno)
- printf("[015 - %d] Error number should not be zero\n", $i);
+ printf("[016 - %d] Error number should not be zero\n", $i);
$i++;
} while ($warning->next());
if (2 != $i)
- printf("[016] Expected 2 warnings, got %d warnings\n", $i);
+ printf("[017] Expected 2 warnings, got %d warnings\n", $i);
mysqli_stmt_close($stmt);
if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
- printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
mysqli_close($link);
print "done!";
diff --git a/ext/mysqli/tests/mysqli_store_result_buffered_c.phpt b/ext/mysqli/tests/mysqli_store_result_buffered_c.phpt
new file mode 100644
index 0000000000..2dec703b99
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_store_result_buffered_c.phpt
@@ -0,0 +1,41 @@
+--TEST--
+mysqli_store_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqlnd.debug=d:t:O,/tmp/mysqlnd.trace
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+
+ require('table.inc');
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[004] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($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));
+
+ mysqli_free_result($res);
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_store_result_copy.phpt b/ext/mysqli/tests/mysqli_store_result_copy.phpt
new file mode 100644
index 0000000000..304300459b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_store_result_copy.phpt
@@ -0,0 +1,285 @@
+--TEST--
+mysqli_store_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!$IS_MYSQLND) {
+ die("SKIP mysqlnd only test");
+}
+?>
+--INI--
+mysqlnd.debug=d:t:O,/tmp/mysqlnd.trace
+mysqlnd.net_read_buffer_size=1
+mysqlnd.mempool_default_size=1
+mysqlnd.fetch_data_copy=0
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ require('table.inc');
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[004] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($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));
+
+ var_dump($res->fetch_assoc());
+
+ if (true !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[006] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ while ($row = $res->fetch_assoc()) {
+ printf("id = %d, label = %s\n", $row['id'], $row['label']);
+ }
+
+ mysqli_free_result($res);
+ mysqli_close($link);
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[007] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[009] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ $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));
+ }
+ } else {
+ $no_result++;
+ }
+ }
+ printf("No result: %d\n", $no_result);
+
+ /* implicit free, implicit store */
+ /* meta and fetch lenghts code */
+ if (!$res = mysqli_query($link, "SELECT CONCAT(id, id) AS _c, label FROM test ORDER BY id DESC LIMIT 2"))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ printf("Default\n");
+ var_dump(mysqli_fetch_lengths($res));
+ $fields = $res->fetch_fields();
+ while ($row = $res->fetch_assoc()) {
+ var_dump(mysqli_fetch_lengths($res));
+ }
+ var_dump(mysqli_fetch_lengths($res));
+
+ if (!$res = mysqli_real_query($link, "SELECT CONCAT(id, id) AS _c, label FROM test ORDER BY id DESC LIMIT 2"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[013] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ printf("Copy\n");
+ var_dump(mysqli_fetch_lengths($res));
+ $fields_copy = $res->fetch_fields();
+ while ($row = $res->fetch_assoc()) {
+ var_dump(mysqli_fetch_lengths($res));
+ }
+ var_dump(mysqli_fetch_lengths($res));
+
+ /* There's no need for in-depth testing here. If you want in-depth switch mysqlnd
+ globally to copy mode and run all the tests */
+ foreach ($fields as $k => $field_info) {
+ if ($fields_copy[$k] != $field_info) {
+ printf("[014] Metadata seems to differ, dumping\n");
+ var_dump($field_info);
+ var_dump($fields_copy[$k]);
+ }
+ }
+
+ /* fetch all */
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id DESC LIMIT 2"))
+ printf("[015] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[016] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ foreach (mysqli_fetch_all($res, MYSQLI_ASSOC) as $row) {
+ printf("id = %d label = %s\n", $row['id'], $row['label']);
+ }
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id DESC LIMIT 2"))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[018] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ /* provoke out of sync */
+ if (!mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id DESC LIMIT 2"))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ var_dump($res->fetch_assoc());
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2"))
+ printf("[020] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA)))
+ printf("[021] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ /* user conn killed, res associated with conn, fetch from res */
+ unset($link);
+ var_dump($res->fetch_assoc());
+
+
+ if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[022] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ if (!$res = mysqli_real_query($link, "INSERT INTO test(id, label) VALUES (100, 'z')"))
+ printf("[023] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA);
+
+ if (mysqli_get_server_version($link) > 50000) {
+ // let's try to play with stored procedures
+ mysqli_real_query($link, 'DROP PROCEDURE IF EXISTS p');
+ if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) READS SQL DATA BEGIN SELECT id FROM test WHERE id >= 100 ORDER BY id; SELECT id + 1, label FROM test WHERE id > 0 AND id < 3 ORDER BY id; SELECT VERSION() INTO ver_param;
+END;')) {
+ mysqli_multi_query($link, "CALL p(@version)");
+ do {
+ if ($res = $link->store_result(MYSQLI_STORE_RESULT_COPY_DATA)) {
+ printf("---\n");
+ var_dump($res->fetch_all());
+ $res->free();
+ } else {
+ if ($link->errno) {
+ echo "Store failed: (" . $link->errno . ") " . $link->error;
+ }
+ }
+ } while ($link->more_results() && $link->next_result());
+ mysqli_real_query($link, 'SELECT @version AS p_version');
+ $res = mysqli_store_result($link, MYSQLI_STORE_RESULT_COPY_DATA);
+
+ $tmp = mysqli_fetch_assoc($res);
+ if (!is_array($tmp) || empty($tmp) || !isset($tmp['p_version']) || ('' == $tmp['p_version'])) {
+ printf("[024] Expecting array [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ var_dump($tmp);
+ }
+
+ mysqli_free_result($res);
+ } else {
+ printf("[025] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+ }
+
+ print "done!";
+?>
+--CLEAN--
+<?php
+ require_once("clean_table.inc");
+?>
+--EXPECTF--
+array(2) {
+ ["id"]=>
+ string(1) "3"
+ ["label"]=>
+ string(1) "c"
+}
+id = 1, label = a
+id = 2, label = b
+id = 3, label = c
+id = 4, label = d
+id = 5, label = e
+id = 6, label = f
+No result: %d
+Default
+bool(false)
+array(2) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(1)
+}
+array(2) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(1)
+}
+bool(false)
+Copy
+bool(false)
+array(2) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(1)
+}
+array(2) {
+ [0]=>
+ int(2)
+ [1]=>
+ int(1)
+}
+bool(false)
+id = 6 label = f
+id = 5 label = e
+array(2) {
+ ["id"]=>
+ string(1) "6"
+ ["label"]=>
+ string(1) "f"
+}
+[020] [2014] %s
+array(2) {
+ ["id"]=>
+ string(1) "6"
+ ["label"]=>
+ string(1) "f"
+}
+---
+array(1) {
+ [0]=>
+ array(1) {
+ [0]=>
+ string(3) "100"
+ }
+}
+---
+array(2) {
+ [0]=>
+ array(2) {
+ [0]=>
+ string(1) "2"
+ [1]=>
+ string(1) "a"
+ }
+ [1]=>
+ array(2) {
+ [0]=>
+ string(1) "3"
+ [1]=>
+ string(1) "b"
+ }
+}
+done! \ No newline at end of file