andrey Tue Nov 18 17:02:18 2008 UTC Added files: (Branch: PHP_5_3) /php-src/ext/mysqli/tests mysqli_poll.phpt mysqli_poll_kill.phpt mysqli_poll_mixing_insert_select.phpt mysqli_poll_reference.phpt
Modified files: /php-src/ext/mysqli mysqli.c mysqli_fe.c mysqli_mysqlnd.h mysqli_nonapi.c mysqli_prop.c php_mysqli_structs.h /php-src/ext/mysqli/tests 057.phpt bug37090.phpt mysqli_class_mysqli_interface.phpt mysqli_constants.phpt /php-src/ext/mysqlnd mysqlnd.c mysqlnd.h mysqlnd_portability.h mysqlnd_structs.h Log: MFH: Asynchronous queries for mysqli, when mysqlnd is enabled. Includes 4 tests for mysqli_poll
http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/mysqli.c?r1=1.72.2.16.2.17.2.31&r2=1.72.2.16.2.17.2.32&diff_format=u Index: php-src/ext/mysqli/mysqli.c diff -u php-src/ext/mysqli/mysqli.c:1.72.2.16.2.17.2.31 php-src/ext/mysqli/mysqli.c:1.72.2.16.2.17.2.32 --- php-src/ext/mysqli/mysqli.c:1.72.2.16.2.17.2.31 Fri Oct 3 16:19:49 2008 +++ php-src/ext/mysqli/mysqli.c Tue Nov 18 17:02:17 2008 @@ -17,7 +17,7 @@ | Ulf Wendel <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ - $Id: mysqli.c,v 1.72.2.16.2.17.2.31 2008/10/03 16:19:49 pajoye Exp $ + $Id: mysqli.c,v 1.72.2.16.2.17.2.32 2008/11/18 17:02:17 andrey Exp $ */ #ifdef HAVE_CONFIG_H @@ -794,6 +794,9 @@ #if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED) REGISTER_LONG_CONSTANT("MYSQLI_BG_STORE_RESULT", MYSQLI_BG_STORE_RESULT, CONST_CS | CONST_PERSISTENT); #endif +#if defined (MYSQLI_USE_MYSQLND) + REGISTER_LONG_CONSTANT("MYSQLI_ASYNC", MYSQLI_ASYNC, CONST_CS | CONST_PERSISTENT); +#endif /* for mysqli_fetch_assoc */ REGISTER_LONG_CONSTANT("MYSQLI_ASSOC", MYSQLI_ASSOC, CONST_CS | CONST_PERSISTENT); http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/mysqli_fe.c?r1=1.49.2.5.2.1.2.10&r2=1.49.2.5.2.1.2.11&diff_format=u Index: php-src/ext/mysqli/mysqli_fe.c diff -u php-src/ext/mysqli/mysqli_fe.c:1.49.2.5.2.1.2.10 php-src/ext/mysqli/mysqli_fe.c:1.49.2.5.2.1.2.11 --- php-src/ext/mysqli/mysqli_fe.c:1.49.2.5.2.1.2.10 Mon Nov 17 11:27:56 2008 +++ php-src/ext/mysqli/mysqli_fe.c Tue Nov 18 17:02:17 2008 @@ -15,7 +15,7 @@ | Author: Georg Richter <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ - $Id: mysqli_fe.c,v 1.49.2.5.2.1.2.10 2008/11/17 11:27:56 felipe Exp $ + $Id: mysqli_fe.c,v 1.49.2.5.2.1.2.11 2008/11/18 17:02:17 andrey Exp $ */ #ifdef HAVE_CONFIG_H @@ -113,12 +113,18 @@ PHP_FE(mysqli_num_rows, NULL) PHP_FE(mysqli_options, NULL) PHP_FE(mysqli_ping, NULL) +#if defined(MYSQLI_USE_MYSQLND) + PHP_FE(mysqli_poll, NULL) +#endif PHP_FE(mysqli_prepare, NULL) PHP_FE(mysqli_report, NULL) PHP_FE(mysqli_query, NULL) PHP_FE(mysqli_real_connect, NULL) PHP_FE(mysqli_real_escape_string, NULL) PHP_FE(mysqli_real_query, NULL) +#if defined(MYSQLI_USE_MYSQLND) + PHP_FE(mysqli_reap_async_query, NULL) +#endif PHP_FE(mysqli_rollback, NULL) PHP_FE(mysqli_select_db, NULL) #ifdef HAVE_MYSQLI_SET_CHARSET @@ -219,6 +225,10 @@ PHP_FALIAS(query,mysqli_query,NULL) PHP_FALIAS(real_connect,mysqli_real_connect,NULL) PHP_FALIAS(real_escape_string,mysqli_real_escape_string,NULL) +#if defined(MYSQLI_USE_MYSQLND) + PHP_FALIAS(poll,mysqli_poll,NULL) + PHP_FALIAS(reap_async_query,mysqli_reap_async_query,NULL) +#endif PHP_FALIAS(escape_string, mysqli_real_escape_string,NULL) PHP_FALIAS(real_query,mysqli_real_query,NULL) PHP_FALIAS(rollback,mysqli_rollback,NULL) @@ -280,11 +290,11 @@ PHP_FALIAS(fetch,mysqli_stmt_fetch,NULL) PHP_FALIAS(get_warnings, mysqli_stmt_get_warnings, NULL) PHP_FALIAS(result_metadata, mysqli_stmt_result_metadata,NULL) - PHP_FALIAS(num_rows, mysqli_stmt_num_rows,NULL) #if defined(MYSQLI_USE_MYSQLND) - PHP_FALIAS(more_results, mysqli_stmt_more_results, NULL) - PHP_FALIAS(next_result, mysqli_stmt_next_result, NULL) + PHP_FALIAS(more_results, mysqli_stmt_more_results,NULL) + PHP_FALIAS(next_result, mysqli_stmt_next_result,NULL) #endif + PHP_FALIAS(num_rows, mysqli_stmt_num_rows,NULL) PHP_FALIAS(send_long_data,mysqli_stmt_send_long_data,NULL) PHP_FALIAS(stmt,mysqli_prepare,NULL) PHP_FALIAS(free_result,mysqli_stmt_free_result,NULL) http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/mysqli_mysqlnd.h?r1=1.3.2.4&r2=1.3.2.5&diff_format=u Index: php-src/ext/mysqli/mysqli_mysqlnd.h diff -u php-src/ext/mysqli/mysqli_mysqlnd.h:1.3.2.4 php-src/ext/mysqli/mysqli_mysqlnd.h:1.3.2.5 --- php-src/ext/mysqli/mysqli_mysqlnd.h:1.3.2.4 Mon Jan 28 18:25:50 2008 +++ php-src/ext/mysqli/mysqli_mysqlnd.h Tue Nov 18 17:02:17 2008 @@ -38,5 +38,6 @@ #define mysqli_stmt_close(c, implicit) mysqlnd_stmt_close((c), (implicit)) #define mysqli_free_result(r, implicit) mysqlnd_free_result((r), (implicit)) #define mysqli_bg_store_result(r) mysqlnd_bg_store_result((r)) +#define mysqli_async_query(c, q, l) mysqlnd_async_query((c), (q), (l)) #endif http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/mysqli_nonapi.c?r1=1.54.2.7.2.5.2.18&r2=1.54.2.7.2.5.2.19&diff_format=u Index: php-src/ext/mysqli/mysqli_nonapi.c diff -u php-src/ext/mysqli/mysqli_nonapi.c:1.54.2.7.2.5.2.18 php-src/ext/mysqli/mysqli_nonapi.c:1.54.2.7.2.5.2.19 --- php-src/ext/mysqli/mysqli_nonapi.c:1.54.2.7.2.5.2.18 Tue Oct 28 15:59:42 2008 +++ php-src/ext/mysqli/mysqli_nonapi.c Tue Nov 18 17:02:17 2008 @@ -17,7 +17,7 @@ | Ulf Wendel <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ - $Id: mysqli_nonapi.c,v 1.54.2.7.2.5.2.18 2008/10/28 15:59:42 andrey Exp $ + $Id: mysqli_nonapi.c,v 1.54.2.7.2.5.2.19 2008/11/18 17:02:17 andrey Exp $ */ #ifdef HAVE_CONFIG_H @@ -533,9 +533,9 @@ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Empty query"); RETURN_FALSE; } - if (resultmode != MYSQLI_USE_RESULT && resultmode != MYSQLI_STORE_RESULT + if ((resultmode & ~MYSQLI_ASYNC) != MYSQLI_USE_RESULT && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_STORE_RESULT #if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED) - && resultmode != MYSQLI_BG_STORE_RESULT + && (resultmode & ~MYSQLI_ASYNC) != MYSQLI_BG_STORE_RESULT #endif ) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid value for resultmode"); @@ -547,6 +547,17 @@ MYSQLI_DISABLE_MQ; +#ifdef MYSQLI_USE_MYSQLND + if (resultmode & MYSQLI_ASYNC) { + if (mysqli_async_query(mysql->mysql, query, query_len)) { + MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); + RETURN_FALSE; + } + mysql->async_result_fetch_type = resultmode & ~MYSQLI_ASYNC; + RETURN_TRUE; + } +#endif + if (mysql_real_query(mysql->mysql, query, query_len)) { MYSQLI_REPORT_MYSQL_ERROR(mysql->mysql); RETURN_FALSE; @@ -592,6 +603,244 @@ #if defined(MYSQLI_USE_MYSQLND) +#include "php_network.h" +/* {{{ mysqlnd_zval_array_to_mysqlnd_array functions */ +static int mysqlnd_zval_array_to_mysqlnd_array(zval *in_array, MYSQLND ***out_array TSRMLS_DC) +{ + zval **elem; + int i = 0, current = 0; + + if (Z_TYPE_P(in_array) != IS_ARRAY) { + return 0; + } + *out_array = ecalloc(zend_hash_num_elements(Z_ARRVAL_P(in_array)) + 1, sizeof(MYSQLND *)); + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_array)); + zend_hash_get_current_data(Z_ARRVAL_P(in_array), (void **) &elem) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(in_array))) { + i++; + if (Z_TYPE_PP(elem) != IS_OBJECT || + !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Parameter %d not a mysqli object", i); + } else { + MY_MYSQL *mysql; + MYSQLI_RESOURCE *my_res; + mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC); + if (!(my_res = (MYSQLI_RESOURCE *)intern->ptr)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "[%d] Couldn't fetch %s", i, intern->zo.ce->name); + continue; + } + mysql = (MY_MYSQL*) my_res->ptr; + if (MYSQLI_STATUS_VALID && my_res->status < MYSQLI_STATUS_VALID) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid object %d or resource %s", i, intern->zo.ce->name); + continue; + } + (*out_array)[current++] = mysql->mysql; + } + } + return 0; +} +/* }}} */ + + +/* {{{ mysqlnd_zval_array_from_mysqlnd_array */ +static int mysqlnd_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *out_array TSRMLS_DC) +{ + MYSQLND **p = in_array; + HashTable *new_hash; + zval **elem, **dest_elem; + int ret = 0; + + ALLOC_HASHTABLE(new_hash); + zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(out_array)), NULL, ZVAL_PTR_DTOR, 0); + + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(out_array)); + zend_hash_get_current_data(Z_ARRVAL_P(out_array), (void **) &elem) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(out_array))) + { + if (Z_TYPE_PP(elem) != IS_OBJECT || !instanceof_function(Z_OBJCE_PP(elem), mysqli_link_class_entry TSRMLS_CC)) { + continue; + } + { + MY_MYSQL *mysql; + mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC); + mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr; + if (mysql->mysql == *p) { + zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem); + if (dest_elem) { + zval_add_ref(dest_elem); + } + ret++; + p++; + } + } + } + + /* destroy old array and add new one */ + zend_hash_destroy(Z_ARRVAL_P(out_array)); + efree(Z_ARRVAL_P(out_array)); + + zend_hash_internal_pointer_reset(new_hash); + Z_ARRVAL_P(out_array) = new_hash; + + return 0; +} +/* }}} */ + + +/* {{{ mysqlnd_dont_poll_zval_array_from_mysqlnd_array */ +static int mysqlnd_dont_poll_zval_array_from_mysqlnd_array(MYSQLND **in_array, zval *in_zval_array, zval *out_array TSRMLS_DC) +{ + MYSQLND **p = in_array; + HashTable *new_hash; + zval **elem, **dest_elem; + int ret = 0; + + ALLOC_HASHTABLE(new_hash); + zend_hash_init(new_hash, zend_hash_num_elements(Z_ARRVAL_P(in_zval_array)), NULL, ZVAL_PTR_DTOR, 0); + if (in_array) { + for (zend_hash_internal_pointer_reset(Z_ARRVAL_P(in_zval_array)); + zend_hash_get_current_data(Z_ARRVAL_P(in_zval_array), (void **) &elem) == SUCCESS; + zend_hash_move_forward(Z_ARRVAL_P(in_zval_array))) + { + MY_MYSQL *mysql; + mysqli_object *intern = (mysqli_object *)zend_object_store_get_object(*elem TSRMLS_CC); + mysql = (MY_MYSQL *) ((MYSQLI_RESOURCE *)intern->ptr)->ptr; + if (mysql->mysql == *p) { + zend_hash_next_index_insert(new_hash, (void *)elem, sizeof(zval *), (void **)&dest_elem); + if (dest_elem) { + zval_add_ref(dest_elem); + } + ret++; + p++; + } + } + } + + /* destroy old array and add new one */ + zend_hash_destroy(Z_ARRVAL_P(out_array)); + efree(Z_ARRVAL_P(out_array)); + + zend_hash_internal_pointer_reset(new_hash); + Z_ARRVAL_P(out_array) = new_hash; + + return 0; +} +/* }}} */ + + +/* {{{ proto int mysqli_poll(array read, array write, array error, long sec [, long usec]) U + Poll connections */ +PHP_FUNCTION(mysqli_poll) +{ + zval *r_array, *e_array, *dont_poll_array; + MYSQLND **new_r_array = NULL, **new_e_array = NULL, **new_dont_poll_array = NULL; + long sec = 0, usec = 0; + enum_func_status ret; + uint desc_num; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!al|l", &r_array, &e_array, &dont_poll_array, &sec, &usec) == FAILURE) { + return; + } + if (sec < 0 || usec < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative values passed for sec and/or usec"); + RETURN_FALSE; + } + + if (r_array != NULL) { + mysqlnd_zval_array_to_mysqlnd_array(r_array, &new_r_array TSRMLS_CC); + } + if (e_array != NULL) { + mysqlnd_zval_array_to_mysqlnd_array(e_array, &new_e_array TSRMLS_CC); + } + + ret = mysqlnd_poll(new_r_array, new_e_array, &new_dont_poll_array, sec, usec, &desc_num); + + mysqlnd_dont_poll_zval_array_from_mysqlnd_array(r_array != NULL ? new_dont_poll_array:NULL, r_array, dont_poll_array TSRMLS_CC); + + if (r_array != NULL) { + mysqlnd_zval_array_from_mysqlnd_array(new_r_array, r_array TSRMLS_CC); + } + if (e_array != NULL) { + mysqlnd_zval_array_from_mysqlnd_array(new_e_array, e_array TSRMLS_CC); + } + + if (new_dont_poll_array) { + efree(new_dont_poll_array); + } + if (new_r_array) { + efree(new_r_array); + } + if (new_e_array) { + efree(new_e_array); + } + if (ret == PASS) { + RETURN_LONG(desc_num); + } else { + RETURN_FALSE; + } +} +/* }}} */ + + +/* {{{ proto int mysqli_reap_async_query(object link) U + Poll connections */ +PHP_FUNCTION(mysqli_reap_async_query) +{ + MY_MYSQL *mysql; + zval *mysql_link; + MYSQLI_RESOURCE *mysqli_resource; + MYSQL_RES *result; + + if (zend_parse_method_parameters(ZEND_NUM_ARGS() TSRMLS_CC, getThis(), "O", &mysql_link, mysqli_link_class_entry) == FAILURE) { + return; + } + + MYSQLI_FETCH_RESOURCE(mysql, MY_MYSQL*, &mysql_link, "mysqli_link", MYSQLI_STATUS_VALID); + + if (FAIL == mysqlnd_reap_async_query(mysql->mysql)) { + RETURN_FALSE; + } + + if (!mysql_field_count(mysql->mysql)) { + /* no result set - not a SELECT */ + if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { +/* php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */ + } + RETURN_TRUE; + } + + switch (mysql->async_result_fetch_type) { + case MYSQLI_STORE_RESULT: + result = mysql_store_result(mysql->mysql); + break; + case MYSQLI_USE_RESULT: + result = mysql_use_result(mysql->mysql); + break; +#if defined(MYSQLI_USE_MYSQLND) && defined(MYSQLND_THREADED) + case MYSQLI_BG_STORE_RESULT: + result = mysqli_bg_store_result(mysql->mysql); + break; +#endif + } + + if (!result) { + php_mysqli_throw_sql_exception((char *)mysql_sqlstate(mysql->mysql), mysql_errno(mysql->mysql) TSRMLS_CC, + "%s", mysql_error(mysql->mysql)); + RETURN_FALSE; + } + + if (MyG(report_mode) & MYSQLI_REPORT_INDEX) { +/* php_mysqli_report_index("n/a", mysqli_server_status(mysql->mysql) TSRMLS_CC); */ + } + + mysqli_resource = (MYSQLI_RESOURCE *)ecalloc (1, sizeof(MYSQLI_RESOURCE)); + mysqli_resource->ptr = (void *)result; + mysqli_resource->status = MYSQLI_STATUS_VALID; + MYSQLI_RETURN_RESOURCE(mysqli_resource, mysqli_result_class_entry); +} +/* }}} */ + + /* {{{ proto object mysqli_stmt_get_result(object link) U Buffer result set on client */ PHP_FUNCTION(mysqli_stmt_get_result) http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/mysqli_prop.c?r1=1.23.2.5.2.2.2.8&r2=1.23.2.5.2.2.2.9&diff_format=u Index: php-src/ext/mysqli/mysqli_prop.c diff -u php-src/ext/mysqli/mysqli_prop.c:1.23.2.5.2.2.2.8 php-src/ext/mysqli/mysqli_prop.c:1.23.2.5.2.2.2.9 --- php-src/ext/mysqli/mysqli_prop.c:1.23.2.5.2.2.2.8 Mon Nov 10 20:06:23 2008 +++ php-src/ext/mysqli/mysqli_prop.c Tue Nov 18 17:02:17 2008 @@ -15,7 +15,7 @@ | Author: Georg Richter <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ - $Id: mysqli_prop.c,v 1.23.2.5.2.2.2.8 2008/11/10 20:06:23 andrey Exp $ + $Id: mysqli_prop.c,v 1.23.2.5.2.2.2.9 2008/11/18 17:02:17 andrey Exp $ */ #ifdef HAVE_CONFIG_H @@ -176,7 +176,7 @@ ZVAL_LONG(*retval, rc); } else { char *ret; - int l = spprintf(&ret, 0, MYSQLI_LLU_SPEC, (my_ulonglong) rc); + int l = spprintf(&ret, 0, MYSQLI_LLU_SPEC, rc); ZVAL_STRINGL(*retval, ret, l, 0); } } @@ -294,7 +294,7 @@ ZVAL_LONG(*retval, rc); } else { char *ret; - int l = spprintf(&ret, 0, MYSQLI_LLU_SPEC, (my_ulonglong) rc); + int l = spprintf(&ret, 0, MYSQLI_LLU_SPEC, rc); ZVAL_STRINGL(*retval, ret, l, 0); } } http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/php_mysqli_structs.h?r1=1.4.2.15&r2=1.4.2.16&diff_format=u Index: php-src/ext/mysqli/php_mysqli_structs.h diff -u php-src/ext/mysqli/php_mysqli_structs.h:1.4.2.15 php-src/ext/mysqli/php_mysqli_structs.h:1.4.2.16 --- php-src/ext/mysqli/php_mysqli_structs.h:1.4.2.15 Mon Jul 21 12:58:51 2008 +++ php-src/ext/mysqli/php_mysqli_structs.h Tue Nov 18 17:02:17 2008 @@ -15,7 +15,7 @@ | Author: Georg Richter <[EMAIL PROTECTED]> | +----------------------------------------------------------------------+ - $Id: php_mysqli_structs.h,v 1.4.2.15 2008/07/21 12:58:51 andrey Exp $ + $Id: php_mysqli_structs.h,v 1.4.2.16 2008/11/18 17:02:17 andrey Exp $ */ #ifndef PHP_MYSQLI_STRUCTS_H @@ -97,8 +97,11 @@ char *hash_key; zval *li_read; php_stream *li_stream; - zend_bool persistent; unsigned int multi_query; + zend_bool persistent; +#if defined(MYSQLI_USE_MYSQLND) + int async_result_fetch_type; +#endif } MY_MYSQL; typedef struct { @@ -299,7 +302,13 @@ #define MYSQLI_STORE_RESULT 0 #define MYSQLI_USE_RESULT 1 #ifdef MYSQLI_USE_MYSQLND -#define MYSQLI_BG_STORE_RESULT 101 +#ifdef MYSQLND_THREADED +#define MYSQLI_BG_STORE_RESULT 4 +#endif +#define MYSQLI_ASYNC 8 +#else +/* libmysql */ +#define MYSQLI_ASYNC 0 #endif /* for mysqli_fetch_assoc */ @@ -433,6 +442,7 @@ PHP_FUNCTION(mysqli_num_rows); PHP_FUNCTION(mysqli_options); PHP_FUNCTION(mysqli_ping); +PHP_FUNCTION(mysqli_poll); PHP_FUNCTION(mysqli_prepare); PHP_FUNCTION(mysqli_query); PHP_FUNCTION(mysqli_stmt_result_metadata); @@ -441,6 +451,7 @@ PHP_FUNCTION(mysqli_real_connect); PHP_FUNCTION(mysqli_real_query); PHP_FUNCTION(mysqli_real_escape_string); +PHP_FUNCTION(mysqli_reap_async_query); PHP_FUNCTION(mysqli_rollback); PHP_FUNCTION(mysqli_row_seek); PHP_FUNCTION(mysqli_select_db); http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/057.phpt?r1=1.4.6.2&r2=1.4.6.3&diff_format=u Index: php-src/ext/mysqli/tests/057.phpt diff -u php-src/ext/mysqli/tests/057.phpt:1.4.6.2 php-src/ext/mysqli/tests/057.phpt:1.4.6.3 --- php-src/ext/mysqli/tests/057.phpt:1.4.6.2 Tue Mar 18 16:57:31 2008 +++ php-src/ext/mysqli/tests/057.phpt Tue Nov 18 17:02:18 2008 @@ -1,8 +1,8 @@ --TEST-- mysqli_get_metadata --SKIPIF-- -<?php -require_once('skipif.inc'); +<?php +require_once('skipif.inc'); require_once('skipifconnectfailure.inc'); ?> --FILE-- http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/bug37090.phpt?r1=1.1.2.3.2.1&r2=1.1.2.3.2.2&diff_format=u Index: php-src/ext/mysqli/tests/bug37090.phpt diff -u php-src/ext/mysqli/tests/bug37090.phpt:1.1.2.3.2.1 php-src/ext/mysqli/tests/bug37090.phpt:1.1.2.3.2.2 --- php-src/ext/mysqli/tests/bug37090.phpt:1.1.2.3.2.1 Wed Oct 10 10:10:59 2007 +++ php-src/ext/mysqli/tests/bug37090.phpt Tue Nov 18 17:02:18 2008 @@ -18,7 +18,7 @@ $mysql = new mysqli($host, $user, $passwd, $db, $port, $socket); $cs = array(); - $cs[] = $mysql->set_charset("latin5"); + $cs[] = $mysql->set_charset("latin1"); $cs[] = $mysql->character_set_name(); $cs[] = $mysql->set_charset("utf8"); @@ -35,7 +35,7 @@ [0]=> bool(true) [1]=> - string(6) "latin5" + string(6) "latin1" [2]=> bool(true) [3]=> @@ -45,4 +45,4 @@ [5]=> string(4) "utf8" } -done! \ No newline at end of file +done! http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt?r1=1.2.2.4&r2=1.2.2.5&diff_format=u Index: php-src/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt diff -u php-src/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt:1.2.2.4 php-src/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt:1.2.2.5 --- php-src/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt:1.2.2.4 Tue Mar 18 16:57:31 2008 +++ php-src/ext/mysqli/tests/mysqli_class_mysqli_interface.phpt Tue Nov 18 17:02:18 2008 @@ -60,6 +60,8 @@ /* $expected_methods['get_cache_stats'] = true; */ /* $expected_methods['get_client_stats'] = true; */ $expected_methods['get_connection_stats'] = true; + $expected_methods['poll'] = true; + $expected_methods['reap_async_query'] = true; } else { // libmysql only if (function_exists('mysqli_ssl_set')) http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_constants.phpt?r1=1.2.2.5&r2=1.2.2.6&diff_format=u Index: php-src/ext/mysqli/tests/mysqli_constants.phpt diff -u php-src/ext/mysqli/tests/mysqli_constants.phpt:1.2.2.5 php-src/ext/mysqli/tests/mysqli_constants.phpt:1.2.2.6 --- php-src/ext/mysqli/tests/mysqli_constants.phpt:1.2.2.5 Mon Oct 27 14:34:35 2008 +++ php-src/ext/mysqli/tests/mysqli_constants.phpt Tue Nov 18 17:02:18 2008 @@ -96,6 +96,7 @@ $expected_constants['MYSQLI_OPT_NET_CMD_BUFFER_SIZE'] = true; $expected_constants['MYSQLI_OPT_NET_READ_BUFFER_SIZE'] = true; $expected_constants['MYSQLI_DEBUG_TRACE_ENABLED'] = true; + $expected_constants['MYSQLI_ASYNC'] = true; } else { $version = mysqli_get_client_version(); http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd.c?r1=1.5.2.31&r2=1.5.2.32&diff_format=u Index: php-src/ext/mysqlnd/mysqlnd.c diff -u php-src/ext/mysqlnd/mysqlnd.c:1.5.2.31 php-src/ext/mysqlnd/mysqlnd.c:1.5.2.32 --- php-src/ext/mysqlnd/mysqlnd.c:1.5.2.31 Thu Nov 6 10:37:47 2008 +++ php-src/ext/mysqlnd/mysqlnd.c Tue Nov 18 17:02:18 2008 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: mysqlnd.c,v 1.5.2.31 2008/11/06 10:37:47 andrey Exp $ */ +/* $Id: mysqlnd.c,v 1.5.2.32 2008/11/18 17:02:18 andrey Exp $ */ #include "php.h" #include "mysqlnd.h" #include "mysqlnd_wireprotocol.h" @@ -870,6 +870,217 @@ /* }}} */ +/* {{{ mysqlnd_conn::send_query */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_conn, send_query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC) +{ + enum_func_status ret; + DBG_ENTER("mysqlnd_conn::send_query"); + DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query); + + ret = mysqlnd_simple_command(conn, COM_QUERY, query, query_len, + PROT_LAST /* we will handle the OK packet*/, + FALSE, FALSE TSRMLS_CC); + CONN_SET_STATE(conn, CONN_QUERY_SENT); + DBG_RETURN(ret); +} +/* }}} */ + +/* {{{ mysqlnd_conn::send_query */ +static enum_func_status +MYSQLND_METHOD(mysqlnd_conn, reap_query)(MYSQLND * conn TSRMLS_DC) +{ + DBG_ENTER("mysqlnd_conn::reap_query"); + DBG_INF_FMT("conn=%llu", conn->thread_id); + enum_mysqlnd_connection_state state = CONN_GET_STATE(conn); + if (state <= CONN_READY || state == CONN_QUIT_SENT) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Connection not opened, clear or has been closed"); + DBG_RETURN(FAIL); + } + DBG_RETURN(mysqlnd_query_read_result_set_header(conn, NULL TSRMLS_CC)); +} +/* }}} */ + + +#include "php_network.h" + +MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array TSRMLS_DC) +{ + int cnt = 0; + MYSQLND **p = conn_array, **p_p; + MYSQLND **ret = NULL; + + while (*p) { + if (CONN_GET_STATE(*p) <= CONN_READY || CONN_GET_STATE(*p) == CONN_QUIT_SENT) { + cnt++; + } + p++; + } + if (cnt) { + MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *)); + p_p = p = conn_array; + while (*p) { + if (CONN_GET_STATE(*p) <= CONN_READY || CONN_GET_STATE(*p) == CONN_QUIT_SENT) { + *ret_p = *p; + *p = NULL; + ret_p++; + } else { + *p_p = *p; + p_p++; + } + p++; + } + *ret_p = NULL; + } + return ret; +} + + +/* {{{ stream_select mysqlnd_stream_array_to_fd_set functions */ +static int mysqlnd_stream_array_to_fd_set(MYSQLND **conn_array, fd_set *fds, php_socket_t *max_fd TSRMLS_DC) +{ + php_socket_t this_fd; + int cnt = 0; + MYSQLND **p = conn_array; + + while (*p) { + /* get the fd. + * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag + * when casting. It is only used here so that the buffered data warning + * is not displayed. + * */ + if (SUCCESS == php_stream_cast((*p)->net.stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, + (void*)&this_fd, 1) && this_fd >= 0) { + + PHP_SAFE_FD_SET(this_fd, fds); + + if (this_fd > *max_fd) { + *max_fd = this_fd; + } + cnt++; + } + p++; + } + return cnt ? 1 : 0; +} + +static int mysqlnd_stream_array_from_fd_set(MYSQLND **conn_array, fd_set *fds TSRMLS_DC) +{ + php_socket_t this_fd; + int ret = 0; + zend_bool disproportion = FALSE; + + + MYSQLND **fwd = conn_array, **bckwd = conn_array; + + while (*fwd) { + if (SUCCESS == php_stream_cast((*fwd)->net.stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, + (void*)&this_fd, 1) && this_fd >= 0) { + if (PHP_SAFE_FD_ISSET(this_fd, fds)) { + if (disproportion) { + *bckwd = *fwd; + } + bckwd++; + fwd++; + ret++; + continue; + } + } + disproportion = TRUE; + fwd++; + } + *bckwd = NULL;/* NULL-terminate the list */ + + return ret; +} + + +#ifndef PHP_WIN32 +#define php_select(m, r, w, e, t) select(m, r, w, e, t) +#else +#include "win32/select.h" +#endif + +/* {{{ _mysqlnd_poll */ +enum_func_status +_mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, uint * desc_num TSRMLS_DC) +{ + + struct timeval tv; + struct timeval *tv_p = NULL; + fd_set rfds, wfds, efds; + php_socket_t max_fd = 0; + int retval, sets = 0; + int set_count, max_set_count = 0; + DBG_ENTER("mysqlnd_poll"); + + if (sec < 0 || usec < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Negative values passed for sec and/or usec"); + DBG_RETURN(FAIL); + } + + *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array TSRMLS_CC); + + FD_ZERO(&rfds); + FD_ZERO(&wfds); + FD_ZERO(&efds); + + if (r_array != NULL) { + set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd TSRMLS_CC); + if (set_count > max_set_count) { + max_set_count = set_count; + } + sets += set_count; + } + + if (e_array != NULL) { + set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd TSRMLS_CC); + if (set_count > max_set_count) { + max_set_count = set_count; + } + sets += set_count; + } + + if (!sets) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed"); + DBG_RETURN(FAIL); + } + + PHP_SAFE_MAX_FD(max_fd, max_set_count); + + /* Solaris + BSD do not like microsecond values which are >= 1 sec */ + if (usec > 999999) { + tv.tv_sec = sec + (usec / 1000000); + tv.tv_usec = usec % 1000000; + } else { + tv.tv_sec = sec; + tv.tv_usec = usec; + } + + tv_p = &tv; + + retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p); + + if (retval == -1) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to select [%d]: %s (max_fd=%d)", + errno, strerror(errno), max_fd); + DBG_RETURN(FAIL); + } + + if (r_array != NULL) { + mysqlnd_stream_array_from_fd_set(r_array, &rfds TSRMLS_CC); + } + if (e_array != NULL) { + mysqlnd_stream_array_from_fd_set(e_array, &efds TSRMLS_CC); + } + + *desc_num = retval; + + DBG_RETURN(PASS); +} +/* }}} */ + + /* COM_FIELD_LIST is special, different from a SHOW FIELDS FROM : - There is no result set header - status from the command, which @@ -1910,6 +2121,8 @@ MYSQLND_METHOD(mysqlnd_conn, escape_string), MYSQLND_METHOD(mysqlnd_conn, set_charset), MYSQLND_METHOD(mysqlnd_conn, query), + MYSQLND_METHOD(mysqlnd_conn, send_query), + MYSQLND_METHOD(mysqlnd_conn, reap_query), MYSQLND_METHOD(mysqlnd_conn, use_result), MYSQLND_METHOD(mysqlnd_conn, store_result), MYSQLND_METHOD(mysqlnd_conn, background_store_result), http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd.h?r1=1.3.2.18&r2=1.3.2.19&diff_format=u Index: php-src/ext/mysqlnd/mysqlnd.h diff -u php-src/ext/mysqlnd/mysqlnd.h:1.3.2.18 php-src/ext/mysqlnd/mysqlnd.h:1.3.2.19 --- php-src/ext/mysqlnd/mysqlnd.h:1.3.2.18 Thu Nov 6 10:37:47 2008 +++ php-src/ext/mysqlnd/mysqlnd.h Tue Nov 18 17:02:18 2008 @@ -18,12 +18,12 @@ +----------------------------------------------------------------------+ */ -/* $Id: mysqlnd.h,v 1.3.2.18 2008/11/06 10:37:47 andrey Exp $ */ +/* $Id: mysqlnd.h,v 1.3.2.19 2008/11/18 17:02:18 andrey Exp $ */ #ifndef MYSQLND_H #define MYSQLND_H -#define MYSQLND_VERSION "mysqlnd 5.0.5-dev - 081106 - $Revision: 1.3.2.18 $" +#define MYSQLND_VERSION "mysqlnd 5.0.5-dev - 081106 - $Revision: 1.3.2.19 $" #define MYSQLND_VERSION_ID 50005 /* This forces inlining of some accessor functions */ @@ -106,8 +106,12 @@ #define mysqlnd_close(conn,is_forced) (conn)->m->close((conn), (is_forced) TSRMLS_CC) #define mysqlnd_query(conn, query_str, query_len) (conn)->m->query((conn), (query_str), (query_len) TSRMLS_CC) +#define mysqlnd_async_query(conn, query_str, query_len) (conn)->m->send_query((conn), (query_str), (query_len) TSRMLS_CC) +#define mysqlnd_poll(r, err, d_pull,sec,usec,desc_num) _mysqlnd_poll((r), (err), (d_pull), (sec), (usec), (desc_num) TSRMLS_CC) +#define mysqlnd_reap_async_query(conn) (conn)->m->reap_query((conn) TSRMLS_CC) #define mysqlnd_unbuffered_skip_result(result) (result)->m.skip_result((result) TSRMLS_CC) +enum_func_status _mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, uint * desc_num TSRMLS_DC); #define mysqlnd_use_result(conn) (conn)->m->use_result((conn) TSRMLS_CC) #define mysqlnd_store_result(conn) (conn)->m->store_result((conn) TSRMLS_CC) http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd_portability.h?r1=1.4.2.11&r2=1.4.2.12&diff_format=u Index: php-src/ext/mysqlnd/mysqlnd_portability.h diff -u php-src/ext/mysqlnd/mysqlnd_portability.h:1.4.2.11 php-src/ext/mysqlnd/mysqlnd_portability.h:1.4.2.12 --- php-src/ext/mysqlnd/mysqlnd_portability.h:1.4.2.11 Thu Nov 6 18:48:55 2008 +++ php-src/ext/mysqlnd/mysqlnd_portability.h Tue Nov 18 17:02:18 2008 @@ -163,8 +163,42 @@ #define L64(x) x##i64 #endif #else + +#if __i386__ +#define MYSQLND_LL_SPEC "%lli" #define MYSQLND_LLU_SPEC "%llu" -#define MYSQLND_LL_SPEC "%lld" +#endif + +#if __ia64__ +#define MYSQLND_LL_SPEC "%li" +#define MYSQLND_LLU_SPEC "%lu" +#endif + +#if __powerpc64__ +#define MYSQLND_LL_SPEC "%li" +#define MYSQLND_LLU_SPEC "%lu" +#endif + +#if __x86_64__ +#define MYSQLND_LL_SPEC "%li" +#define MYSQLND_LLU_SPEC "%lu" +#endif + +#if __s390x__ +#define MYSQLND_LL_SPEC "%li" +#define MYSQLND_LLU_SPEC "%lu" +#endif + +#if __powerpc__ && !__powerpc64__ +#define MYSQLND_LL_SPEC "%lli" +#define MYSQLND_LLU_SPEC "%llu" +#endif + +#if __s390__ && !__s390x__ +#define MYSQLND_LL_SPEC "%lli" +#define MYSQLND_LLU_SPEC "%llu" +#endif + #define MYSQLND_SZ_T_SPEC "%zd" #ifndef L64 #define L64(x) x##LL http://cvs.php.net/viewvc.cgi/php-src/ext/mysqlnd/mysqlnd_structs.h?r1=1.2.2.16&r2=1.2.2.17&diff_format=u Index: php-src/ext/mysqlnd/mysqlnd_structs.h diff -u php-src/ext/mysqlnd/mysqlnd_structs.h:1.2.2.16 php-src/ext/mysqlnd/mysqlnd_structs.h:1.2.2.17 --- php-src/ext/mysqlnd/mysqlnd_structs.h:1.2.2.16 Thu Nov 6 10:37:47 2008 +++ php-src/ext/mysqlnd/mysqlnd_structs.h Tue Nov 18 17:02:18 2008 @@ -18,7 +18,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: mysqlnd_structs.h,v 1.2.2.16 2008/11/06 10:37:47 andrey Exp $ */ +/* $Id: mysqlnd_structs.h,v 1.2.2.17 2008/11/18 17:02:18 andrey Exp $ */ #ifndef MYSQLND_STRUCTS_H #define MYSQLND_STRUCTS_H @@ -237,6 +237,8 @@ ulong (*escape_string)(const MYSQLND * const conn, char *newstr, const char *escapestr, size_t escapestr_len TSRMLS_DC); enum_func_status (*set_charset)(MYSQLND * const conn, const char * const charset TSRMLS_DC); enum_func_status (*query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC); + enum_func_status (*send_query)(MYSQLND *conn, const char *query, unsigned int query_len TSRMLS_DC); + enum_func_status (*reap_query)(MYSQLND *conn TSRMLS_DC); MYSQLND_RES * (*use_result)(MYSQLND * const conn TSRMLS_DC); MYSQLND_RES * (*store_result)(MYSQLND * const conn TSRMLS_DC); MYSQLND_RES * (*background_store_result)(MYSQLND * const conn TSRMLS_DC); http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_poll.phpt?view=markup&rev=1.1 Index: php-src/ext/mysqli/tests/mysqli_poll.phpt +++ php-src/ext/mysqli/tests/mysqli_poll.phpt --TEST-- int mysqli_poll() simple --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 = 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_poll())) printf("[002] Expecting NULL got %s\n", var_export($tmp, true)); if (NULL !== ($tmp = @mysqli_poll(array($link)))) printf("[003] Expecting NULL got %s\n", var_export($tmp, true)); if (NULL !== ($tmp = @mysqli_poll(array($link), NULL))) printf("[004] Expecting NULL got %s\n", var_export($tmp, true)); if (NULL !== ($tmp = @mysqli_poll(array($link), NULL, NULL))) printf("[005] Expecting NULL got %s\n", var_export($tmp, true)); $int_val = 43; $myerrors = &$int_val; if (NULL !== ($tmp = @mysqli_poll(array($link), $myerrors, NULL, 1))) printf("[006] Expecting NULL got %s\n", var_export($tmp, true)); if (NULL !== ($tmp = @mysqli_poll(array($link), NULL, NULL, -1))) printf("[007] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true)); if (NULL !== ($tmp = @mysqli_poll(array($link), NULL, NULL, 0, -1))) printf("[008] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true)); if (0 !== ($tmp = (mysqli_poll(array($link), array($link), array($link), 0, 1)))) printf("[009] Expecting int/0 got %s/%s\n", gettype($tmp), var_export($tmp, true)); function poll_async($offset, $links, $errors, $reject, $exp_ready) { 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", $exp_ready, $tmp); foreach ($links as $mysqli) { if (is_object($res = mysqli_reap_async_query($mysqli))) { printf("[%03d + 2] Can fetch resultset although no query has been run!\n", $offset); } 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(); $links = array($link); $errors = array($link); $reject = array($link); poll_async(10, $links, $errors, $reject, 0); mysqli_close($link); // Connections on which no query has been send - 2 // Difference: pass $links twice $link = get_connection(); $links = array($link, $link); $errors = array($link, $link); $reject = array(); poll_async(11, $links, $errors, $reject, 0); // Connections on which no query has been send - 3 // Difference: pass two connections $link = get_connection(); $links = array($link, get_connection()); $errors = array($link, $link); $reject = array(); poll_async(12, $links, $errors, $reject, 0); // Reference mess... $link = get_connection(); $links = array($link); $errors = array($link); $ref_errors =& $errors; $reject = array(); poll_async(13, $links, $ref_errors, $reject, 0); print "done!"; ?> --EXPECTF-- [010 + 6] Rejecting thread %d: 0/ [011 + 6] Rejecting thread %d: 0/ [011 + 6] Rejecting thread %d: 0/ [012 + 6] Rejecting thread %d: 0/ [012 + 6] Rejecting thread %d: 0/ [013 + 6] Rejecting thread %d: 0/ done! http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_poll_kill.phpt?view=markup&rev=1.1 Index: php-src/ext/mysqli/tests/mysqli_poll_kill.phpt +++ php-src/ext/mysqli/tests/mysqli_poll_kill.phpt --TEST-- int mysqli_poll() and kill --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 = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); return $link; } // Killing connection - 1 $link = get_connection(); if (true !== ($tmp = mysqli_query($link, "SELECT 1 AS 'processed beofre killed'", MYSQLI_ASYNC | MYSQLI_USE_RESULT))) printf("[002] Expecting boolean/true got %s/%s\n", gettype($tmp), var_export($tmp, true)); // Sleep 0.1s - the asynchronous query should have been processed after the wait period usleep(100000); $thread_id = mysqli_thread_id($link); mysqli_kill(get_connection(), $thread_id); $links = array($link); $errors = array($link); $reject = array($link); // Yes, 1 - the asynchronous query should have been processed if (1 !== ($tmp = (mysqli_poll($links, $errors, $reject, 0, 10000)))) printf("[003] Expecting int/1 got %s/%s\n", gettype($tmp), var_export($tmp, true)); if (!is_array($links) || empty($links)) printf("[004] 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))) { // Yes, you can fetch a result - the query has been processed var_dump(mysqli_fetch_assoc($res)); mysqli_free_result($res); } else if ($link->errno > 0) { printf("[005] Error: %d\n", $link->errno); } } // No error! if (!is_array($errors) || !empty($errors)) printf("[006] Expecting non-empty array got %s/%s\n", gettype($errors), var_export($errors, true)); if (!is_array($reject) || !empty($reject)) printf("[007] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true)); // Lets pass a dead connection $links = array($link); $errors = array($link); $reject = array($link); if (0 !== ($tmp = mysqli_poll($links, $errors, $reject, 1))) printf("[008] There should be no connection ready! Returned %s/%s, expecting int/0.\n", gettype($tmp), var_export($tmp, true)); if (!empty($errors)) printf("[009] There should be no errors but one rejected connection\n"); foreach ($reject as $mysqli) if (mysqli_thread_id($mysqli) != $thread_id) { printf("[010] Rejected thread %d should have rejected thread %d\n", mysqli_thread_id($mysqli), $thread_id); } // Killing connection - 2 $link = get_connection(); if (true !== ($tmp = mysqli_query($link, "SELECT 1", MYSQLI_ASYNC | MYSQLI_USE_RESULT))) printf("[011] Expecting boolean/true got %s/%s\n", gettype($tmp), var_export($tmp, true)); usleep(100000); $thread_id = mysqli_thread_id($link); mysqli_kill(get_connection(), $thread_id); // Yes, 1 - fetch OK packet of kill! $processed = 0; do { $links = array($link, $link); $errors = array($link, $link); $reject = array($link, $link); $ready = mysqli_poll($links, $errors, $reject, 1); if (!empty($errors)) { foreach ($errors as $mysqli) { printf("[012] Error on thread %d: %s/%s\n", mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli)); } break; } if (!empty($reject)) { foreach ($reject as $mysqli) { printf("[013] Rejecting thread %d: %s/%s\n", mysqli_thread_id($mysqli), mysqli_errno($mysqli), mysqli_error($mysqli)); } $processed += count($reject); } foreach ($links as $mysqli) { if (is_object($res = mysqli_reap_async_query($mysqli))) { 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)); } $processed++; } } while ($processed < 2); // Killing connection - 3 $link = get_connection(); $thread_id = mysqli_thread_id($link); mysqli_kill(get_connection(), $thread_id); // Sleep 0.1s to ensure the KILL gets recognized usleep(100000); if (false !== ($tmp = mysqli_query($link, "SELECT 1 AS 'processed beofre killed'", MYSQLI_ASYNC | MYSQLI_USE_RESULT))) printf("[015] Expecting boolean/false got %s/%s\n", gettype($tmp), var_export($tmp, true)); $links = array($link); $errors = array($link); $reject = array($link); // Yes, that is weird, right? Its the OK package we have to fetch if (1 !== ($tmp = (mysqli_poll($links, $errors, $reject, 0, 10000)))) printf("[016] 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)); else foreach ($links as $link) { if (is_object($res = mysqli_reap_async_query($link))) { // No, you cannot fetch the result var_dump(mysqli_fetch_assoc($res)); 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); } } // 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)); if (!is_array($reject) || !empty($reject)) printf("[020] Expecting empty array got %s/%s\n", gettype($reject), var_export($reject, true)); mysqli_close($link); print "done!"; ?> --EXPECTF-- array(1) { ["processed beofre killed"]=> string(1) "1" } Fetching from thread %d... array(1) { [1]=> string(1) "1" } Warning: mysqli_reap_async_query(): GREET %s Warning: mysqli_reap_async_query(): MySQL server has gone away in %s on line %d [014] 2014/%s Warning: Error while sending QUERY packet. PID=%d in %s on line %d Warning: mysqli_reap_async_query(): MySQL server has gone away in %s on line %d Warning: mysqli_reap_async_query(): Error reading result set's header in %s on line %d [018] Error: 2006/%s done! http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt?view=markup&rev=1.1 Index: php-src/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt +++ php-src/ext/mysqli/tests/mysqli_poll_mixing_insert_select.phpt --TEST-- mysqli_poll() & INSERT SELECT --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('table.inc'); function get_connection() { global $host, $user, $passwd, $db, $port, $socket; if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); return $link; } // Note: some queries will fail! They are supposed to fail. $queries = array( 'CREATE TABLE IF NOT EXISTS bogus(id INT)', 'SET @a = 1', 'SELECT * FROM test ORDER BY id ASC LIMIT 2', 'INSERT INTO test(id, label) VALUES (100, "z")', 'SELECT * FROM test ORDER BY id ASC LIMIT 2', 'SELECT', 'UPDATE test SET id = 101 WHERE id > 3', 'UPDATE_FIX test SET id = 101 WHERE id > 3', 'DROP TABLE IF EXISTS bogus', 'DELETE FROM test WHERE id = @a', 'DELETE FROM test WHERE id = 1', ); $link = get_connection(); $have_proc = false; mysqli_real_query($link, "DROP PROCEDURE IF EXISTS p"); if (mysqli_real_query($link, 'CREATE PROCEDURE p(IN ver_in VARCHAR(25), OUT ver_out VARCHAR(25)) BEGIN SELECT ver_in INTO ver_out; END;')) { $have_proc = true; $queries[] = 'CALL p("myversion", @version)'; } mysqli_close($link); $links = array(); for ($i = 0; $i < count($queries); $i++) { $link = get_connection(); if (true !== ($tmp = mysqli_query($link, $queries[$i], MYSQLI_ASYNC | MYSQLI_USE_RESULT))) printf("[002] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true)); // WARNING KLUDGE NOTE // Add a tiny delay to ensure that queries get executed in a certain order // If your MySQL server is very slow the test may randomly fail! usleep(20000); $links[mysqli_thread_id($link)] = array( 'query' => $queries[$i], 'link' => $link, 'processed' => false, ); } $saved_errors = array(); do { $poll_links = $poll_errors = $poll_reject = array(); foreach ($links as $thread_id => $link) { if (!$link['processed']) { $poll_links[] = $link['link']; $poll_errors[] = $link['link']; $poll_reject[] = $link['link']; } } if (0 == count($poll_links)) break; if (0 == ($num_ready = mysqli_poll($poll_links, $poll_errors, $poll_reject, 0, 200000))) continue; if (!empty($poll_errors)) { die(var_dump($poll_errors)); } foreach ($poll_links as $link) { $thread_id = mysqli_thread_id($link); $links[$thread_id]['processed'] = true; if (is_object($res = mysqli_reap_async_query($link))) { // result set object while ($row = mysqli_fetch_assoc($res)) { // eat up all results ; } mysqli_free_result($res); } else { // either there is no result (no SELECT) or there is an error if (mysqli_errno($link) > 0) { $saved_errors[$thread_id] = mysqli_errno($link); printf("[003] '%s' caused %d\n", $links[$thread_id]['query'], mysqli_errno($link)); } } } } while (true); // Checking if all lines are still usable foreach ($links as $thread_id => $link) { if (isset($saved_errors[$thread_id]) && $saved_errors[$thread_id] != mysqli_errno($link['link'])) { printf("[004] Error state not saved for query '%s', %d != %d\n", $link['query'], $saved_errors[$thread_id], mysqli_errno($link['link'])); } if (!$res = mysqli_query($link['link'], 'SELECT * FROM test WHERE id = 100')) printf("[005] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true)); if (!$row = mysqli_fetch_row($res)) printf("[006] Expecting true got %s/%s\n", gettype($tmp), var_export($tmp, true)); mysqli_free_result($res); } if ($res = mysqli_query($link['link'], "SELECT * FROM test WHERE id = 100")) { $row = mysqli_fetch_assoc($res); var_dump($row); mysqli_free_result($res); } if ($have_proc && ($res = mysqli_query($link['link'], "SELECT @version as _version"))) { $row = mysqli_fetch_assoc($res); if ($row['_version'] != 'myversion') { printf("[007] Check procedures\n"); } mysqli_free_result($res); } foreach ($links as $link) mysqli_close($link['link']); $link = get_connection(); if (!mysqli_query($link, 'SELECT 1', MYSQLI_ASYNC)) printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); if (!mysqli_query($link, 'SELECT 1', MYSQLI_ASYNC)) printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link)); mysqli_close($link); print "done!"; ?> --EXPECTF-- [003] 'SELECT' caused 1064 [003] 'UPDATE test SET id = 101 WHERE id > 3' caused 1062 [003] 'UPDATE_FIX test SET id = 101 WHERE id > 3' caused 1064 array(2) { ["id"]=> string(3) "100" ["label"]=> string(1) "z" } [009] [2014] %s done! http://cvs.php.net/viewvc.cgi/php-src/ext/mysqli/tests/mysqli_poll_reference.phpt?view=markup&rev=1.1 Index: php-src/ext/mysqli/tests/mysqli_poll_reference.phpt +++ php-src/ext/mysqli/tests/mysqli_poll_reference.phpt --TEST-- mysqli_poll() & references --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"); if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) die("skip cannot connect"); if (mysqli_server_version($link) < 50012)) die("skip Test needs SQL function SLEEP() available as of MySQL 5.0.12"); mysqli_close($link); ?> --FILE-- <?php require_once('connect.inc'); function get_connection() { global $host, $user, $passwd, $db, $port, $socket; if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); return $link; } $mysqli1 = get_connection(); $mysqli2 = get_connection(); var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); $processed = $loops = 0; do { $loops++; if ($loops > 10) { printf("[002] The queries should have finished already\n"); break; } // WARNING: All arrays point to the same object - this will give bogus results! // The behaviour is in line with stream_select(). Be warned, be careful. $links = $errors = $reject = array($mysqli1, $mysqli2); if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) { continue; } foreach ($links as $link) { if ($res = mysqli_reap_async_query($link)) { mysqli_free_result($res); } $processed++; } } while ($processed < 2); mysqli_close($mysqli1); mysqli_close($mysqli2); $mysqli1 = get_connection(); $mysqli2 = get_connection(); var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); $processed = $loops = 0; do { $loops++; if ($loops > 10) { printf("[003] The queries should have finished already\n"); break; } // WARNING: All arrays point to the same object - this will give bogus results! $links = $errors = array($mysqli1, $mysqli2); $reject = array($mysqli1, $mysqli2); if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) { continue; } foreach ($links as $link) { if ($res = mysqli_reap_async_query($link)) { mysqli_free_result($res); } $processed++; } } while ($processed < 2); mysqli_close($mysqli1); mysqli_close($mysqli2); $mysqli1 = get_connection(); $mysqli2 = get_connection(); var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); $processed = $loops = 0; do { $loops++; if ($loops > 10) { printf("[004] The queries should have finished already\n"); break; } // WARNING: All arrays point to the same object - this will give bogus results! $links = array($mysqli1, $mysqli2); $errors = $reject = array($mysqli1, $mysqli2); if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) { continue; } foreach ($links as $link) { if ($res = mysqli_reap_async_query($link)) { mysqli_free_result($res); } $processed++; } } while ($processed < 2); mysqli_close($mysqli1); mysqli_close($mysqli2); // This is bogus code and bogus usage - OK to throw no errors! $mysqli1 = get_connection(); $mysqli2 = get_connection(); var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); $thread_id = mysqli_thread_id($mysqli2); printf("Connection %d should be rejected...\n", $thread_id); $processed = $loops = 0; do { $loops++; if ($loops > 10) { printf("[005] The queries should have finished already\n"); break; } $links = $errors = $reject = array($mysqli1, $mysqli2); if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) { continue; } // WARNING: Due to the reference issue none of these should ever fire! foreach ($reject as $links) { printf("Connection %d was rejected...\n", mysqli_thread_id($link)); $processed++; } foreach ($errors as $links) { printf("Connection %d has an error...\n", mysqli_thread_id($link)); $processed++; } foreach ($links as $link) { if ($res = mysqli_reap_async_query($link)) { mysqli_free_result($res); $processed++; } } } while ($processed < 2); mysqli_close($mysqli1); mysqli_close($mysqli2); $mysqli1 = get_connection(); $mysqli2 = get_connection(); var_dump(mysqli_query($mysqli1, "SELECT SLEEP(0.10)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); var_dump(mysqli_query($mysqli2, "SELECT SLEEP(0.20)", MYSQLI_ASYNC | MYSQLI_USE_RESULT)); $processed = $loops = 0; $all = array($mysqli1, $mysqli2); do { $loops++; if ($loops > 10) { printf("[006] The queries should have finished already\n"); break; } $links = $errors = $reject = $all; ob_start(); if (0 == ($ready = mysqli_poll($links, $errors, $reject, 0, 50000))) { $tmp = ob_get_contents(); ob_end_clean(); if ($tmp != '') { printf("Expected error:\n%s\n", $tmp); break; } continue; } foreach ($links as $link) { if ($res = mysqli_reap_async_query($link)) { mysqli_free_result($res); } $processed++; } } while ($processed < 2); mysqli_close($mysqli1); mysqli_close($mysqli2); print "done!"; ?> --EXPECTF-- bool(true) bool(true) [002] The queries should have finished already bool(true) bool(true) [003] The queries should have finished already bool(true) bool(true) bool(true) Connection %d should be rejected... [005] The queries should have finished already bool(true) bool(true) Expected error: Warning: mysqli_poll(): No stream arrays were passed in %s on line %d done!
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php