diff options
Diffstat (limited to 'ext/mysqli')
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  | 
