]> granicus.if.org Git - php/commitdiff
More updates to the ext/mysqli tests in HEAD = synching with 5_3
authorUlf Wendel <uw@php.net>
Wed, 10 Oct 2007 10:46:06 +0000 (10:46 +0000)
committerUlf Wendel <uw@php.net>
Wed, 10 Oct 2007 10:46:06 +0000 (10:46 +0000)
29 files changed:
ext/mysqli/tests/mysqli_get_client_stats.phpt
ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_get_client_stats_off.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_get_client_stats_ps.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_max_links.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_no_reconnect.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_options_openbasedir.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_pconn_disabled.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_pconn_kill.phpt [new file with mode: 0755]
ext/mysqli/tests/mysqli_pconn_limits.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_pconn_max_links.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_pconn_reuse.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_query_stored_proc.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_big5.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_reconnect.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt
ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt [new file with mode: 0644]
ext/mysqli/tests/mysqli_stmt_get_result_types.phpt [new file with mode: 0644]
ext/mysqli/tests/skipifunicode.inc [new file with mode: 0644]

index e7d91b3e5a57579941be01184ce85cf0d94d353d..042f14bd99c43b06b9630582d53ae4de41fca508 100644 (file)
@@ -9,6 +9,9 @@ if (!function_exists('mysqli_get_client_stats')) {
        die("skip only available with mysqlnd");
 }
 ?>
+--INI--
+mysqlnd.collect_statistics=1
+mysqlnd.collect_memory_statistics=1
 --FILE--
 <?php
        /*
@@ -101,7 +104,7 @@ if (!function_exists('mysqli_get_client_stats')) {
                printf("[005] Expecting the same number of entries in the arrays\n");
                var_dump($info);
                var_dump($new_info);
-               }
+       }
 
        $test_counter = 6;
        mysqli_get_client_stats_assert_gt('bytes_sent', $new_info, $info, $test_counter);
@@ -121,9 +124,8 @@ if (!function_exists('mysqli_get_client_stats')) {
        mysqli_get_client_stats_assert_eq('unbuffered_sets', $new_info, $info, $test_counter);
        mysqli_get_client_stats_assert_eq('ps_buffered_sets', $new_info, $info, $test_counter);
        mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $new_info, $info, $test_counter);
-       mysqli_get_client_stats_assert_eq('rows_fetched_from_server', $new_info, $info, $test_counter);
-       mysqli_get_client_stats_assert_eq('rows_fetched_from_client', $new_info, $info, $test_counter);
-       mysqli_get_client_stats_assert_eq('rows_skipped', $new_info, $info, $test_counter);
+
+       mysqli_get_client_stats_assert_eq('rows_skipped_ps', $new_info, $info, $test_counter);
        mysqli_get_client_stats_assert_eq('copy_on_write_saved', $new_info, $info, $test_counter);
        mysqli_get_client_stats_assert_eq('copy_on_write_performed', $new_info, $info, $test_counter);
        mysqli_get_client_stats_assert_eq('command_buffer_too_small', $new_info, $info, $test_counter);
@@ -134,6 +136,355 @@ if (!function_exists('mysqli_get_client_stats')) {
        mysqli_get_client_stats_assert_eq('connection_reused', $new_info, $info, $test_counter);
 
        require('table.inc');
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       // fetch stats
+       $expected = $info;
+
+       // buffered normal
+       print "Testing buffered normal...\n";
+       if (!$res = mysqli_query($link, 'SELECT COUNT(*) AS _num FROM test', MYSQLI_STORE_RESULT))
+               printf("[%03d] SELECT COUNT() FROM test failed, [%d] %s\n",
+                       ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+       $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + 1);
+       $expected['buffered_sets'] = (string)($expected['buffered_sets'] + 1);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+       $expected['rows_buffered_from_client_normal'] = (string)($expected['rows_buffered_from_client_normal'] + 1);
+
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('buffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+
+       /* no change to rows_fetched_from_client_normal_buffered! */
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[%03d] fetch_assoc - SELECT COUNT() FROM test failed, [%d] %s\n",
+                       ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+       $expected['rows_fetched_from_client_normal_buffered'] = (string)($expected['rows_fetched_from_client_normal_buffered'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+
+       $num_rows = $row['_num'];
+       mysqli_free_result($res);
+
+       print "Testing buffered normal... - SELECT id, label FROM test\n";
+       if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_STORE_RESULT))
+               printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
+                       ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+       assert(mysqli_num_rows($res) == $num_rows);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows);
+       $expected['rows_buffered_from_client_normal'] = (string)($expected['rows_buffered_from_client_normal'] + $num_rows);
+       $expected['buffered_sets'] = (string)($expected['buffered_sets'] + 1);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('buffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_normal', $info, $expected, $test_counter);
+
+       /* fetching none, but stats should not be affected - current implementation */
+       mysqli_free_result($res);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_buffered', $info, $expected, $test_counter);
+
+       print "Testing unbuffered normal...\n";
+       if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_USE_RESULT))
+               printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
+                       ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+
+       while ($row = mysqli_fetch_assoc($res))
+               ;
+       mysqli_free_result($res);
+
+       $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows);
+       $expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + $num_rows);
+       $expected['unbuffered_sets'] = (string)($expected['unbuffered_sets'] + 1);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('unbuffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+
+       print "Testing unbuffered normal... - SELECT id, label FROM test, not all fetched\n";
+       if (!$res = mysqli_query($link, 'SELECT id, label FROM test', MYSQLI_USE_RESULT))
+               printf("[%03d] SELECT id, label FROM test failed, [%d] %s\n",
+                       ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+       for ($i = 0; $i < $num_rows - 1; $i++)
+               $row = mysqli_fetch_assoc($res);
+
+       $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + $num_rows - 1);
+       $expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + $num_rows - 1);
+       $expected['unbuffered_sets'] = (string)($expected['unbuffered_sets'] + 1);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('unbuffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+
+       print "Testing if implicit fetching and cleaning happens...\n";
+       mysqli_free_result($res);
+
+       /* last row has been implicitly cleaned from the wire by freeing the result set */
+       $expected['rows_fetched_from_server_normal'] = (string)($expected['rows_fetched_from_server_normal'] + 1);
+       $expected['rows_fetched_from_client_normal_unbuffered'] = (string)($expected['rows_fetched_from_client_normal_unbuffered'] + 1);
+       $expected['rows_skipped_normal'] = (string)($info['rows_skipped_normal'] + 1);
+       $expected['flushed_normal_sets'] = (string)($expected['flushed_normal_sets'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_normal_unbuffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_skipped_normal', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('flushed_normal_sets', $info, $expected, $test_counter);
+
+       print "Testing buffered Prepared Statements...\n";
+       if (!$stmt = mysqli_stmt_init($link))
+               printf("[%03d] stmt_init() failed, [%d] %s\n",
+                       ++$test_counter, mysqli_errno($link), mysqli_error($link));
+
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+                       !mysqli_stmt_execute($stmt))
+               printf("[%03d] prepare/execute failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       /* by default PS is unbuffered - no change */
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+
+       if (!mysqli_stmt_store_result($stmt))
+               printf("[%03d] store_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+       mysqli_stmt_free_result($stmt);
+
+       $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+       $expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
+       $expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
+
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+       print "Testing buffered Prepared Statements... - fetching all\n";
+
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+                       !mysqli_stmt_execute($stmt))
+               printf("[%03d] prepare/execute failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $id = $label = null;
+       if (!mysqli_stmt_bind_result($stmt, $id, $label))
+               printf("[%03d] bind_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       if (!mysqli_stmt_store_result($stmt))
+               printf("[%03d] store_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       while (mysqli_stmt_fetch($stmt))
+               ;
+
+       $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+       $expected['rows_fetched_from_client_ps_buffered'] = (string)($expected['rows_fetched_from_client_ps_buffered'] + $num_rows);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+       $expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
+       $expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+       mysqli_stmt_free_result($stmt);
+
+       print "Testing buffered Prepared Statements... - fetching all but one\n";
+
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+                       !mysqli_stmt_execute($stmt))
+               printf("[%03d] prepare/execute failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $id = $label = null;
+       if (!mysqli_stmt_bind_result($stmt, $id, $label))
+               printf("[%03d] bind_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       if (!mysqli_stmt_store_result($stmt))
+               printf("[%03d] store_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       for ($i = 0; $i < $num_rows - 1; $i++)
+               mysqli_stmt_fetch($stmt);
+
+       $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+       $expected['rows_fetched_from_client_ps_buffered'] = (string)($expected['rows_fetched_from_client_ps_buffered'] + $num_rows - 1);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+       $expected['ps_buffered_sets'] = (string)($expected['ps_buffered_sets'] + 1);
+       $expected['rows_buffered_from_client_ps'] = (string)($expected['rows_buffered_from_client_ps'] + $num_rows);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_buffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('ps_buffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+       $expected['rows_skipped_ps'] = $info['rows_skipped_ps'];
+       mysqli_stmt_free_result($stmt);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       /* buffered result set - no skipping possible! */
+       mysqli_get_client_stats_assert_eq('rows_skipped_ps', $info, $expected, $test_counter);
+
+       print "Testing unbuffered Prepared Statements... - fetching all\n";
+
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+                       !mysqli_stmt_execute($stmt))
+               printf("[%03d] prepare/execute failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $id = $label = null;
+       if (!mysqli_stmt_bind_result($stmt, $id, $label))
+               printf("[%03d] bind_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $i = 0;
+       while (mysqli_stmt_fetch($stmt))
+               $i++;
+       assert($num_rows = $i);
+
+       $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows);
+       $expected['rows_fetched_from_client_ps_unbuffered'] = (string)($expected['rows_fetched_from_client_ps_unbuffered'] + $num_rows);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+       $expected['ps_unbuffered_sets'] = (string)($expected['ps_unbuffered_sets'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_unbuffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+       mysqli_stmt_free_result($stmt);
+
+       print "Testing unbuffered Prepared Statements... - fetching all but one\n";
+
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test') ||
+                       !mysqli_stmt_execute($stmt))
+               printf("[%03d] prepare/execute failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $id = $label = null;
+       if (!mysqli_stmt_bind_result($stmt, $id, $label))
+               printf("[%03d] bind_result failed, [%d] %s\n",
+                       ++$test_counter, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       for ($i = 0; $i < $num_rows - 1; $i++)
+               mysqli_stmt_fetch($stmt);
+
+       $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + $num_rows - 1);
+       $expected['rows_fetched_from_client_ps_unbuffered'] = (string)($expected['rows_fetched_from_client_ps_unbuffered'] + $num_rows - 1);
+       $expected['result_set_queries'] = (string)($expected['result_set_queries'] + 1);
+       $expected['ps_unbuffered_sets'] = (string)($expected['ps_unbuffered_sets'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_client_ps_unbuffered', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('result_set_queries', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('ps_unbuffered_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_buffered_from_client_ps', $info, $expected, $test_counter);
+
+       mysqli_stmt_free_result($stmt);
+       $expected['rows_skipped_ps'] = (string)($expected['rows_skipped_ps'] + 1);
+       $expected['flushed_ps_sets'] = (string)($expected['flushed_ps_sets'] + 1);
+       $expected['rows_fetched_from_server_ps'] = (string)($expected['rows_fetched_from_server_ps'] + 1);
+
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
+       mysqli_get_client_stats_assert_eq('rows_skipped_ps', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('flushed_ps_sets', $info, $expected, $test_counter);
+       mysqli_get_client_stats_assert_eq('rows_fetched_from_server_ps', $info, $expected, $test_counter);
+
+       /*
+       print "Checking for normal buffered side effects...\n";
+       foreach ($info as $k => $v)
+               if ($info[$k] != $expected[$k])
+                       printf("$k - $v != %s\n", $expected[$k]);
+       */
+       print "... done with fetch statistics\n";
+
        if (!is_array($info = mysqli_get_client_stats()) || empty($info))
                printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
                        ++$test_counter, gettype($info), $info);
@@ -142,6 +493,10 @@ if (!function_exists('mysqli_get_client_stats')) {
        // result_set_queries statistics
        //
 
+       if (!is_array($info = mysqli_get_client_stats()) || empty($info))
+               printf("[%03d] Expecting array/any_non_empty, got %s/%s\n",
+                       ++$test_counter, gettype($info), $info);
+
        if (!$res = mysqli_query($link, "SELECT id, label FROM test"))
                printf("[%03d] SELECT failed, [%d] %s\n", ++$test_counter,
                        mysqli_errno($link), mysqli_error($link));
@@ -504,7 +859,7 @@ if (!function_exists('mysqli_get_client_stats')) {
        print "done!";
 ?>
 --EXPECTF--
-array(33) {
+array(61) {
   ["bytes_sent"]=>
   string(1) "0"
   ["bytes_received"]=>
@@ -537,11 +892,31 @@ array(33) {
   string(1) "0"
   ["flushed_ps_sets"]=>
   string(1) "0"
-  ["rows_fetched_from_server"]=>
+  ["ps_prepared_never_executed"]=>
+  string(1) "0"
+  ["ps_prepared_once_executed"]=>
+  string(1) "0"
+  ["rows_fetched_from_server_normal"]=>
+  string(1) "0"
+  ["rows_fetched_from_server_ps"]=>
+  string(1) "0"
+  ["rows_buffered_from_client_normal"]=>
+  string(1) "0"
+  ["rows_buffered_from_client_ps"]=>
+  string(1) "0"
+  ["rows_fetched_from_client_normal_buffered"]=>
+  string(1) "0"
+  ["rows_fetched_from_client_normal_unbuffered"]=>
   string(1) "0"
-  ["rows_fetched_from_client"]=>
+  ["rows_fetched_from_client_ps_buffered"]=>
   string(1) "0"
-  ["rows_skipped"]=>
+  ["rows_fetched_from_client_ps_unbuffered"]=>
+  string(1) "0"
+  ["rows_fetched_from_client_ps_cursor"]=>
+  string(1) "0"
+  ["rows_skipped_normal"]=>
+  string(1) "0"
+  ["rows_skipped_ps"]=>
   string(1) "0"
   ["copy_on_write_saved"]=>
   string(1) "0"
@@ -555,6 +930,14 @@ array(33) {
   string(1) "0"
   ["connection_reused"]=>
   string(1) "0"
+  ["reconnect"]=>
+  string(1) "0"
+  ["pconnect_success"]=>
+  string(1) "0"
+  ["active_connections"]=>
+  string(1) "0"
+  ["active_persistent_connections"]=>
+  string(1) "0"
   ["explicit_close"]=>
   string(1) "0"
   ["implicit_close"]=>
@@ -571,10 +954,49 @@ array(33) {
   string(1) "0"
   ["implicit_stmt_close"]=>
   string(1) "0"
+  ["mem_emalloc_count"]=>
+  string(1) "0"
+  ["mem_emalloc_ammount"]=>
+  string(1) "0"
+  ["mem_ecalloc_count"]=>
+  string(1) "0"
+  ["mem_ecalloc_ammount"]=>
+  string(1) "0"
+  ["mem_erealloc_count"]=>
+  string(1) "0"
+  ["mem_erealloc_ammount"]=>
+  string(1) "0"
+  ["mem_efree_count"]=>
+  string(1) "0"
+  ["mem_malloc_count"]=>
+  string(1) "0"
+  ["mem_malloc_ammount"]=>
+  string(1) "0"
+  ["mem_calloc_count"]=>
+  string(1) "0"
+  ["mem_calloc_ammount"]=>
+  string(1) "0"
+  ["mem_realloc_calloc"]=>
+  string(1) "0"
+  ["mem_realloc_ammount"]=>
+  string(1) "0"
+  ["mem_free_count"]=>
+  string(1) "0"
 }
+Testing buffered normal...
+Testing buffered normal... - SELECT id, label FROM test
+Testing unbuffered normal...
+Testing unbuffered normal... - SELECT id, label FROM test, not all fetched
+Testing if implicit fetching and cleaning happens...
+Testing buffered Prepared Statements...
+Testing buffered Prepared Statements... - fetching all
+Testing buffered Prepared Statements... - fetching all but one
+Testing unbuffered Prepared Statements... - fetching all
+Testing unbuffered Prepared Statements... - fetching all but one
+... done with fetch statistics
 done!
 --UEXPECTF--
-array(33) {
+array(61) {
   [u"bytes_sent"]=>
   unicode(1) "0"
   [u"bytes_received"]=>
@@ -607,11 +1029,31 @@ array(33) {
   unicode(1) "0"
   [u"flushed_ps_sets"]=>
   unicode(1) "0"
-  [u"rows_fetched_from_server"]=>
+  [u"ps_prepared_never_executed"]=>
+  unicode(1) "0"
+  [u"ps_prepared_once_executed"]=>
+  unicode(1) "0"
+  [u"rows_fetched_from_server_normal"]=>
+  unicode(1) "0"
+  [u"rows_fetched_from_server_ps"]=>
+  unicode(1) "0"
+  [u"rows_buffered_from_client_normal"]=>
   unicode(1) "0"
-  [u"rows_fetched_from_client"]=>
+  [u"rows_buffered_from_client_ps"]=>
   unicode(1) "0"
-  [u"rows_skipped"]=>
+  [u"rows_fetched_from_client_normal_buffered"]=>
+  unicode(1) "0"
+  [u"rows_fetched_from_client_normal_unbuffered"]=>
+  unicode(1) "0"
+  [u"rows_fetched_from_client_ps_buffered"]=>
+  unicode(1) "0"
+  [u"rows_fetched_from_client_ps_unbuffered"]=>
+  unicode(1) "0"
+  [u"rows_fetched_from_client_ps_cursor"]=>
+  unicode(1) "0"
+  [u"rows_skipped_normal"]=>
+  unicode(1) "0"
+  [u"rows_skipped_ps"]=>
   unicode(1) "0"
   [u"copy_on_write_saved"]=>
   unicode(1) "0"
@@ -625,6 +1067,14 @@ array(33) {
   unicode(1) "0"
   [u"connection_reused"]=>
   unicode(1) "0"
+  [u"reconnect"]=>
+  unicode(1) "0"
+  [u"pconnect_success"]=>
+  unicode(1) "0"
+  [u"active_connections"]=>
+  unicode(1) "0"
+  [u"active_persistent_connections"]=>
+  unicode(1) "0"
   [u"explicit_close"]=>
   unicode(1) "0"
   [u"implicit_close"]=>
@@ -641,5 +1091,44 @@ array(33) {
   unicode(1) "0"
   [u"implicit_stmt_close"]=>
   unicode(1) "0"
+  [u"mem_emalloc_count"]=>
+  unicode(1) "0"
+  [u"mem_emalloc_ammount"]=>
+  unicode(1) "0"
+  [u"mem_ecalloc_count"]=>
+  unicode(1) "0"
+  [u"mem_ecalloc_ammount"]=>
+  unicode(1) "0"
+  [u"mem_erealloc_count"]=>
+  unicode(1) "0"
+  [u"mem_erealloc_ammount"]=>
+  unicode(1) "0"
+  [u"mem_efree_count"]=>
+  unicode(1) "0"
+  [u"mem_malloc_count"]=>
+  unicode(1) "0"
+  [u"mem_malloc_ammount"]=>
+  unicode(1) "0"
+  [u"mem_calloc_count"]=>
+  unicode(1) "0"
+  [u"mem_calloc_ammount"]=>
+  unicode(1) "0"
+  [u"mem_realloc_calloc"]=>
+  unicode(1) "0"
+  [u"mem_realloc_ammount"]=>
+  unicode(1) "0"
+  [u"mem_free_count"]=>
+  unicode(1) "0"
 }
-done!
\ No newline at end of file
+Testing buffered normal...
+Testing buffered normal... - SELECT id, label FROM test
+Testing unbuffered normal...
+Testing unbuffered normal... - SELECT id, label FROM test, not all fetched
+Testing if implicit fetching and cleaning happens...
+Testing buffered Prepared Statements...
+Testing buffered Prepared Statements... - fetching all
+Testing buffered Prepared Statements... - fetching all but one
+Testing unbuffered Prepared Statements... - fetching all
+Testing unbuffered Prepared Statements... - fetching all but one
+... done with fetch statistics
+done!
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt b/ext/mysqli/tests/mysqli_get_client_stats_implicit_free.phpt
new file mode 100644 (file)
index 0000000..6d835ab
--- /dev/null
@@ -0,0 +1,42 @@
+--TEST--
+mysqli_get_client_stats() - implicit_free_result
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+       die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=1
+mysqlnd.collect_memory_statistics=1
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       $stats = mysqli_get_client_stats();
+       printf("BEGINNING: implicit_free_result = %d\n",        $stats['implicit_free_result']);
+
+       if (!$res = mysqli_query($link, 'SELECT id FROM test'))
+               printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res);
+       mysqli_close($link);
+
+       $after = mysqli_get_client_stats();
+       if ($after['implicit_free_result'] != $stats['implicit_free_result'])
+               printf("[002] Where is the missing mysqli_free_result() call? implicit_free_result has changed by %d.\n",
+                       $after['implicit_free_result'] - $stats['implicit_free_result']);
+
+       $stats = $after;
+       printf("END: implicit_free_result = %d\n",      $stats['implicit_free_result']);
+
+       print "done!";
+?>
+--EXPECTF--
+BEGINNING: implicit_free_result = %d
+END: implicit_free_result = %d
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_off.phpt b/ext/mysqli/tests/mysqli_get_client_stats_off.phpt
new file mode 100644 (file)
index 0000000..8a731ca
--- /dev/null
@@ -0,0 +1,38 @@
+--TEST--
+mysqli_get_client_stats() - php_ini setting
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+       die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=0
+mysqlnd.collect_memory_statistics=0
+--FILE--
+<?php
+       $before = mysqli_get_client_stats();
+       // connect and table inc connect to mysql and create tables
+       require_once('connect.inc');
+       require_once('table.inc');
+       $after = mysqli_get_client_stats();
+
+       if (!is_array($before) || empty($before)) {
+               printf("[001] Expecting non-empty array, got %s.\n", gettype($before));
+               var_dump($before);
+       }
+
+       foreach ($after as $k => $v)
+               if ($v != 0) {
+                       printf("[002] Field %s should not have any other value but 0, got %s.\n",
+                               $k, $v);
+               }
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_ps.phpt b/ext/mysqli/tests/mysqli_get_client_stats_ps.phpt
new file mode 100644 (file)
index 0000000..fea641b
--- /dev/null
@@ -0,0 +1,102 @@
+--TEST--
+mysqli_get_client_stats() - PS
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+       die("skip only available with mysqlnd");
+}
+?>
+--INI--
+mysqlnd.collect_statistics=1
+mysqlnd.collect_memory_statistics=1
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       $stats = mysqli_get_client_stats();
+       printf("BEGINNING: rows_fetched_from_client_ps_unbuffered = %d\n",      $stats['rows_fetched_from_client_ps_unbuffered']);
+       printf("BEGINNING: rows_fetched_from_client_ps_buffered = %d\n",        $stats['rows_fetched_from_client_ps_buffered']);
+       printf("BEGINNING: rows_fetched_from_client_ps_cursor = %d\n",  $stats['rows_fetched_from_client_ps_cursor']);
+
+       if (!$stmt = mysqli_stmt_init($link))
+               printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       $id = null;
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id FROM test') ||
+                       !mysqli_stmt_execute($stmt) ||
+                       !mysqli_stmt_store_result($stmt) ||
+                       !mysqli_stmt_bind_result($stmt, $id))
+               printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $num_rows = 0;
+       while (mysqli_stmt_fetch($stmt))
+               $num_rows++;
+
+       mysqli_stmt_free_result($stmt);
+
+       $after = mysqli_get_client_stats();
+
+       if ($after['rows_fetched_from_client_ps_unbuffered'] != $stats['rows_fetched_from_client_ps_unbuffered'])
+               printf("[003] Unbuffered rows got increased after buffered PS, expecting %d got %d.\n",
+                       $stats['rows_fetched_from_client_ps_unbuffered'],
+                       $after['rows_fetched_from_client_ps_unbuffered']);
+
+       $stats['rows_fetched_from_client_ps_buffered'] += $num_rows;
+       if ($after['rows_fetched_from_client_ps_buffered'] != $stats['rows_fetched_from_client_ps_buffered'] )
+               printf("[005] Buffered rows should be %d got %d.\n",
+                       $stats['rows_fetched_from_client_ps_buffered'],
+                       $after['rows_fetched_from_client_ps_buffered']);
+
+       $stats = $after;
+       printf("BUFFERED: rows_fetched_from_client_ps_unbuffered = %d\n",       $stats['rows_fetched_from_client_ps_unbuffered']);
+       printf("BUFFERED: rows_fetched_from_client_ps_buffered = %d\n", $stats['rows_fetched_from_client_ps_buffered']);
+       printf("BUFFERED: rows_fetched_from_client_ps_cursor = %d\n",   $stats['rows_fetched_from_client_ps_cursor']);
+
+       $id = null;
+       if (!mysqli_stmt_prepare($stmt, 'SELECT id FROM test') ||
+                       !mysqli_stmt_execute($stmt) ||
+                       !mysqli_stmt_bind_result($stmt, $id))
+               printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+       $num_rows = 0;
+       while (mysqli_stmt_fetch($stmt))
+               $num_rows++;
+
+       $after = mysqli_get_client_stats();
+       $stats['rows_fetched_from_client_ps_unbuffered'] += $num_rows;
+       if ($after['rows_fetched_from_client_ps_unbuffered'] != $stats['rows_fetched_from_client_ps_unbuffered'])
+               printf("[007] Unbuffered rows should be %d got %d.\n",
+                       $stats['rows_fetched_from_client_ps_unbuffered'],
+                       $after['rows_fetched_from_client_ps_unbuffered']);
+
+       if ($after['rows_fetched_from_client_ps_buffered'] != $stats['rows_fetched_from_client_ps_buffered'] )
+               printf("[005] Buffered rows should be unchanged, expecting %d got %d.\n",
+                       $stats['rows_fetched_from_client_ps_buffered'],
+                       $after['rows_fetched_from_client_ps_buffered']);
+
+       mysqli_stmt_free_result($stmt);
+       mysqli_stmt_close($stmt);
+
+       $stats = $after;
+       printf("UNBUFFERED: rows_fetched_from_client_ps_unbuffered = %d\n",     $stats['rows_fetched_from_client_ps_unbuffered']);
+       printf("UNBUFFERED: rows_fetched_from_client_ps_buffered = %d\n",       $stats['rows_fetched_from_client_ps_buffered']);
+       printf("UNBUFFERED: rows_fetched_from_client_ps_cursor = %d\n", $stats['rows_fetched_from_client_ps_cursor']);
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+BEGINNING: rows_fetched_from_client_ps_unbuffered = %d
+BEGINNING: rows_fetched_from_client_ps_buffered = %d
+BEGINNING: rows_fetched_from_client_ps_cursor = 0
+BUFFERED: rows_fetched_from_client_ps_unbuffered = %d
+BUFFERED: rows_fetched_from_client_ps_buffered = %d
+BUFFERED: rows_fetched_from_client_ps_cursor = 0
+UNBUFFERED: rows_fetched_from_client_ps_unbuffered = %d
+UNBUFFERED: rows_fetched_from_client_ps_buffered = %d
+UNBUFFERED: rows_fetched_from_client_ps_cursor = 0
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt b/ext/mysqli/tests/mysqli_get_client_stats_skipped.phpt
new file mode 100644 (file)
index 0000000..9dd802d
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+mysqli_get_client_stats() - skipped rows
+--SKIPIF--
+<?PHP
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_get_client_stats')) {
+       die("skip only available with mysqlnd");
+}
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       if (!$res = mysqli_query($link, 'SELECT id FROM test', MYSQLI_STORE_RESULT))
+               printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       $num_rows = mysqli_num_rows($res);
+       assert($num_rows > 2);
+       mysqli_free_result($res);
+
+       $before = mysqli_get_client_stats();
+       printf("BEFORE: rows_skipped_normal = %d\n", $before['rows_skipped_normal']);
+
+       if (!$res = mysqli_query($link, 'SELECT id FROM test', MYSQLI_USE_RESULT))
+               printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       /* fetch all rows but the last one */
+       for ($i = 0; $i < $num_rows - 1; $i++)
+               $row = mysqli_fetch_assoc($res);
+
+       /* enforce implicit cleaning of the wire and skipping the last row */
+       mysqli_free_result($res);
+       $after = mysqli_get_client_stats();
+       printf("AFTER: rows_skipped_normal = %d\n", $after['rows_skipped_normal']);
+
+       if ($after['rows_skipped_normal'] != $before['rows_skipped_normal'] + 1)
+               printf("Statistics should show an increase of 1 for rows_skipped_normal, ".
+                               "but before=%d after=%d\n", $before['rows_skipped_normal'], $after['rows_skipped_normal']);
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+BEFORE: rows_skipped_normal = %d
+AFTER: rows_skipped_normal = %d
+done!
diff --git a/ext/mysqli/tests/mysqli_max_links.phpt b/ext/mysqli/tests/mysqli_max_links.phpt
new file mode 100644 (file)
index 0000000..a9a7980
--- /dev/null
@@ -0,0 +1,72 @@
+--TEST--
+Testing mysqli.max_links
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.max_links=1
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once("table.inc");
+
+       // to make sure we have at least one working connection...
+       var_dump(mysqli_ping($link));
+       // to make sure that max_links is really set to one
+       var_dump((int)ini_get('mysqli.max_links'));
+
+       $links = array();
+       for ($i = 1; $i <= 5; $i++)
+               if ($links[$i] = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+                       printf("[%03d] One link is already open, it should not be possible to open more, [%d] %s, [%d] %s\n",
+                               $i, mysqli_connect_errno(), mysqli_connect_error(),
+                               mysqli_errno($links[$i]), mysqli_error($links[$i]));
+
+       for ($i = 1; $i <= 5; $i++) {
+               if ($res = mysqli_query($links[$i], 'SELECT id FROM test LIMIT 1')) {
+                       printf("[%03d] Can run query on link %d\n", 5 + $i, $i);
+                       mysqli_free_result($res);
+               }
+               mysqli_close($links[$i]);
+       }
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+int(1)
+
+Warning: mysqli_connect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_connect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_connect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_connect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_connect(): Too many open links (1) in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_query() expects parameter 1 to be mysqli, boolean given in %s on line %d
+
+Warning: mysqli_close() expects parameter 1 to be mysqli, boolean given in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_no_reconnect.phpt b/ext/mysqli/tests/mysqli_no_reconnect.phpt
new file mode 100644 (file)
index 0000000..d392b5a
--- /dev/null
@@ -0,0 +1,111 @@
+--TEST--
+Trying implicit reconnect after wait_timeout and KILL using mysqli_ping()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+mysqli.reconnect=0
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once("table.inc");
+
+       if (!$link2 = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] Cannot create second database connection, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       $thread_id_timeout = mysqli_thread_id($link);
+       $thread_id_control = mysqli_thread_id($link2);
+
+       if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+               printf("[002] Cannot get full processlist, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (!isset($running_threads[$thread_id_timeout]) ||
+                       !isset($running_threads[$thread_id_control]))
+               printf("[003] Processlist is borked, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       if (!mysqli_query($link, "SET SESSION wait_timeout = 2"))
+               printf("[004] Cannot set wait_timeout, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'wait_timeout'"))
+               printf("[005] Cannot check if wait_timeout has been set, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[006] Cannot get wait_timeout, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       if ($row['Value'] != 2)
+               printf("[007] Failed setting the wait_timeout, test will not work, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       // after 2+ seconds the server should kill the connection
+       sleep(3);
+
+       if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+               printf("[008] Cannot get full processlist, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (isset($running_threads[$thread_id_timeout]))
+               printf("[009] Server should have killed the timeout connection, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       if (false !== @mysqli_ping($link))
+               printf("[010] Reconnect should not have happened");
+
+       if ($res = @mysqli_query($link, "SELECT DATABASE() as _dbname"))
+               printf("[011] Executing a query should not be possible, connection should be closed, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       if (!$link = @mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[012] Cannot create database connection, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       $thread_id_timeout = mysqli_thread_id($link);
+       if (!mysqli_query($link, sprintf('KILL %d', $thread_id_timeout)))
+               printf("[013] Cannot KILL timeout connection, [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+       // Give the server a second to really kill the other thread...
+       sleep(1);
+
+       if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+               printf("[014] Cannot get full processlist, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (isset($running_threads[$thread_id_timeout]) ||
+                       !isset($running_threads[$thread_id_control]))
+               printf("[015] Processlist is borked, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       if (false !== ($tmp = @mysqli_ping($link)))
+               printf("[016] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+       if ($res = @mysqli_query($link, "SELECT DATABASE() as _dbname"))
+               printf("[017] Running a query should not be possible, connection should be gone, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       mysqli_close($link2);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_options_openbasedir.phpt b/ext/mysqli/tests/mysqli_options_openbasedir.phpt
new file mode 100644 (file)
index 0000000..d5a5bf4
--- /dev/null
@@ -0,0 +1,24 @@
+--TEST--
+mysqli_options() - MYSQLI_OPT_LOCAL_INFILE and open_basedir
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+open_basedir="."
+--FILE--
+<?php
+       require_once('connect.inc');
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] Cannot connect, [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       if (false !== mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, 1))
+               printf("[002] Can set MYSQLI_OPT_LOCAL_INFILE although open_basedir is set!\n");
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_pconn_disabled.phpt b/ext/mysqli/tests/mysqli_pconn_disabled.phpt
new file mode 100644 (file)
index 0000000..746dd3b
--- /dev/null
@@ -0,0 +1,63 @@
+--TEST--
+mysqli_pconnect() - mysqli.allow_persistent = 0
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!stristr(mysqli_get_client_info(), 'mysqlnd'))
+       die("skip: only available in mysqlnd");
+?>
+--INI--
+mysqli.allow_persistent=0
+mysqli.max_persistent=2
+mysqli.max_links=2
+--FILE--
+<?php
+       include "connect.inc";
+
+       $host = 'p:' . $host;
+       if (!$link1 = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+               // automatic downgrade to normal connections has failed
+               printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+                       $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+       }
+       if (!mysqli_query($link1, 'SET @pcondisabled = "Connection 1"'))
+               printf("[002] Cannot set user variable to check if we got the same persistent connection, [%d] %s\n",
+                       mysqli_errno($link1), mysqli_error($link1));
+
+       if (!$link2 = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+               // automatic downgrade to normal connections has failed
+               printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+                       $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+       }
+
+       if (!$res = mysqli_query($link1, 'SELECT @pcondisabled AS _test'))
+               printf("[004] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       printf("Connecction 1 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+       mysqli_free_result($res);
+
+       if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+               printf("[005] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       printf("Connecction 2 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+       mysqli_free_result($res);
+
+       if ($link1 === $link2)
+               printf("[006] Links should not be identical\n");
+
+       mysqli_close($link1);
+       mysqli_close($link2);
+       print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_connect(): Persistent connections are disabled. Downgrading to normal in %s on line %d
+
+Warning: mysqli_connect(): Persistent connections are disabled. Downgrading to normal in %s on line %d
+Connecction 1 - SELECT @pcondisabled -> 'Connection 1'
+Connecction 2 - SELECT @pcondisabled -> ''
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_kill.phpt b/ext/mysqli/tests/mysqli_pconn_kill.phpt
new file mode 100755 (executable)
index 0000000..61d5624
--- /dev/null
@@ -0,0 +1,95 @@
+--TEST--
+Killing a persistent connection.
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+if (!$IS_MYSQLND)
+       die("skip mysqlnd test only");
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=2
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once("table.inc");
+
+       $host = 'p:' . $host;
+       if (!$plink = 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);
+
+       // get the thread ids of the two connections...
+       $thread_id = mysqli_thread_id($link);
+       $pthread_id = mysqli_thread_id($plink);
+
+       if (!$res = mysqli_query($link, 'SHOW FULL PROCESSLIST'))
+               printf("[002] Cannot get processlist, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (count($running_threads) < 2)
+               printf("[003] Processlist is too short, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!isset($running_threads[$thread_id]))
+               printf("[004] Cannot find thread id of the regular link, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!isset($running_threads[$pthread_id]))
+               printf("[005] Cannot find thread id of the persistent link, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       // Kill the persistent connection - don't use mysqli_kill, mysqlnd will catch that...
+       if (!mysqli_query($link, sprintf('KILL %d', $pthread_id)))
+               printf("[006] Cannot kill persistent connection, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       mysqli_close($plink);
+       // Give the server think-time to kill the pthread
+       sleep(1);
+
+       if (!$res = mysqli_query($link, 'SHOW FULL PROCESSLIST'))
+               printf("[007] Cannot get processlist, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       $running_threads2 = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads2[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (isset($running_threads2[$pthread_id]))
+               printf("[008] Thread of the persistent connection should have been gone, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       if (!isset($running_threads2[$thread_id]))
+               printf("[009] Thread of the regular connection should be still there, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       // On PHP side this should do nothing. PHP should not try to close the connection or something.
+       @mysqli_close($plink);
+
+       if (!$plink = @mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[011] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+                       $host, $user, $db, $port, $socket);
+       if (!$res3 = @mysqli_query($plink, 'SELECT id FROM test ORDER BY id LIMIT 1')) {
+               printf("[012] New persistent connection cannot execute queries, [%d] %s\n", @mysqli_errno($plink), @mysqli_error($plink));
+       }
+
+       @mysqli_free_result($res3);
+       @mysqli_close($plink);
+       mysqli_close($link);
+
+       // remove the "p:<host>" from the host variable
+       $host = substr($host, 2);
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[013] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+                       $host, $user, $db, $port, $socket);
+       if (!$res4 = mysqli_query($link, 'SELECT id FROM test ORDER BY id LIMIT 1'))
+               printf("[014] New regular connection cannot execute queries, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res4);
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
+--UEXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_pconn_limits.phpt b/ext/mysqli/tests/mysqli_pconn_limits.phpt
new file mode 100644 (file)
index 0000000..774154d
--- /dev/null
@@ -0,0 +1,96 @@
+--TEST--
+Persistent connections - limits (-1, unlimited)
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once("connect.inc");
+if (!$IS_MYSQLND)
+       die("skip mysqlnd test only");
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=-1
+mysqli.max_links=-1
+--FILE--
+<?php
+       require_once("connect.inc");
+       // opens a regular connection
+       require_once("table.inc");
+
+       if (!$res = mysqli_query($link, 'SELECT "works.." as _desc'))
+               printf("[001] Cannot run query, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       $row = mysqli_fetch_assoc($res);
+       mysqli_free_result($res);
+       printf("Regular connection 1 - '%s'\n", $row['_desc']);
+
+       if (!$link2 = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[002] Cannot open second regular connection, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$res = mysqli_query($link2, 'SELECT "works..." as _desc'))
+               printf("[003] Cannot run query, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       mysqli_free_result($res);
+       printf("Regular connection 2 - '%s'\n", $row['_desc']);
+
+       $host = 'p:' . $host;
+       if (!$plink = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[004] Cannot create persistent connection using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+                       $host, $user, $db, $port, $socket,
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$res = mysqli_query($plink, 'SELECT "works..." as _desc'))
+               printf("[005] Cannot run query, [%d] %s\n",
+                       mysqli_errno($plink), mysqli_error($plink));
+
+       $row = mysqli_fetch_assoc($res);
+       mysqli_free_result($res);
+       printf("Persistent connection 1 - '%s'\n", $row['_desc']);
+
+       if (!$plink2 = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[006] Cannot create persistent connection using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+                       $host, $user, $db, $port, $socket,
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$res = mysqli_query($plink2, 'SELECT "works..." as _desc'))
+               printf("[007] Cannot run query, [%d] %s\n",
+                       mysqli_errno($plink2), mysqli_error($plink2));
+
+       $row = mysqli_fetch_assoc($res);
+       mysqli_free_result($res);
+       printf("Persistent connection 2 - '%s'\n", $row['_desc']);
+
+       $plink3 = mysqli_init();
+       if (!mysqli_real_connect($plink3, $host, $user, $passwd, $db, $port, $socket))
+               printf("[008] Cannot create persistent connection using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s, [%d] %s\n",
+                       $host, $user, $db, $port, $socket,
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$res = mysqli_query($plink3, 'SELECT "works..." as _desc'))
+               printf("[009] Cannot run query, [%d] %s\n",
+                       mysqli_errno($plink2), mysqli_error($plink2));
+
+       $row = mysqli_fetch_assoc($res);
+       mysqli_free_result($res);
+       printf("Persistent connection 3 - '%s'\n", $row['_desc']);
+
+       mysqli_close($link);
+       mysqli_close($link2);
+       mysqli_close($plink);
+       mysqli_close($plink2);
+       mysqli_close($plink3);
+       print "done!";
+?>
+--EXPECTF--
+Regular connection 1 - 'works..'
+Regular connection 2 - 'works...'
+Persistent connection 1 - 'works...'
+Persistent connection 2 - 'works...'
+Persistent connection 3 - 'works...'
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_max_links.phpt b/ext/mysqli/tests/mysqli_pconn_max_links.phpt
new file mode 100644 (file)
index 0000000..8b47728
--- /dev/null
@@ -0,0 +1,172 @@
+--TEST--
+Persistent connections and mysqli.max_links
+--SKIPIF--
+<?php
+       require_once('skipif.inc');
+       require_once('skipifemb.inc');
+       require_once('skipifconnectfailure.inc');
+       require_once('connect.inc');
+
+       if (!$IS_MYSQLND)
+               die("skip mysqlnd only test");
+
+       // we need a second DB user to test for a possible flaw in the ext/mysql[i] code
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               die(sprintf("skip Cannot connect [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+       mysqli_query($link, 'DROP USER pcontest');
+       if (!mysqli_query($link, 'CREATE USER pcontest IDENTIFIED BY "pcontest"')) {
+               printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+               mysqli_close($link);
+               die();
+       }
+
+       // we might be able to specify the host using CURRENT_USER(), but...
+       if (!mysqli_query($link, sprintf("GRANT SELECT ON TABLE %s.test TO pcontest@'%%'", $db))) {
+               printf("skip Cannot GRANT SELECT to second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
+               mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
+               mysqli_query($link, 'DROP USER pcontest');
+               mysqli_close($link);
+               die();
+       }
+       mysqli_close($link);
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=2
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       if (!$plink = 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());
+
+       ob_start();
+       phpinfo();
+       $phpinfo = strip_tags(ob_get_contents());
+       ob_end_clean();
+
+       $phpinfo = substr($phpinfo, strpos($phpinfo, 'MysqlI Support => enabled'), 500);
+       if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
+               printf("[002] Cannot get # active persistent links from phpinfo()\n");
+       $num_plinks = $matches[1];
+
+       if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
+               printf("[003] Cannot run query on persistent connection of second DB user, [%d] %s\n",
+                       mysqli_errno($plink), mysqli_error($plink));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[004] Cannot run fetch result, [%d] %s\n",
+                       mysqli_errno($plink), mysqli_error($plink));
+       mysqli_free_result($res);
+       var_dump($row);
+
+       // change the password for the second DB user and kill the persistent connection
+       if (!mysqli_query($link, 'SET PASSWORD FOR pcontest = PASSWORD("newpass")') ||
+                       !mysqli_query($link, 'FLUSH PRIVILEGES'))
+               printf("[005] Cannot change PW of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       // persistent connections cannot be closed but only be killed
+       $pthread_id = mysqli_thread_id($plink);
+       if (!mysqli_query($link, sprintf('KILL %d', $pthread_id)))
+               printf("[006] Cannot KILL persistent connection of second DB user, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       // give the server a second to really kill the thread
+       sleep(1);
+
+       if (!$res = mysqli_query($link, "SHOW FULL PROCESSLIST"))
+               printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (isset($running_threads[$pthread_id]))
+               printf("[008] Persistent connection has not been killed\n");
+
+       // this fails and we have 0 (<= $num_plinks) connections
+       if ($plink = @mysqli_connect('p:' . $host, 'pcontest', 'pcontest', $db, $port, $socket))
+               printf("[009] Can connect using the old password, [%d] %s\n",
+                       mysqli_connect_errno($link), mysqli_connect_error($link));
+
+       ob_start();
+       phpinfo();
+       $phpinfo = strip_tags(ob_get_contents());
+       ob_end_clean();
+       $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
+       if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
+               printf("[010] Cannot get # of active persistent links from phpinfo()\n");
+
+       $num_plinks_kill = $matches[1];
+       if ($num_plinks_kill > $num_plinks)
+               printf("[011] Expecting Active Persistent Links < %d, got %d\n", $num_plinks, $num_plinks_kill);
+
+       if (!$plink = mysqli_connect('p:' . $host, 'pcontest', 'newpass', $db, $port, $socket))
+               printf("[012] Cannot connect using the new password, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       if (!$res = mysqli_query($plink, 'SELECT id, label FROM test WHERE id = 1'))
+               printf("[013] Cannot run query on persistent connection of second DB user, [%d] %s\n",
+                       mysqli_errno($plink), mysqli_error($plink));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[014] Cannot run fetch result, [%d] %s\n",
+                       mysqli_errno($plink), mysqli_error($plink));
+       mysqli_free_result($res);
+       var_dump($row);
+
+       if ($plink2 = 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());
+
+       ob_start();
+       phpinfo();
+       $phpinfo = strip_tags(ob_get_contents());
+       ob_end_clean();
+       $phpinfo = substr($phpinfo, stripos($phpinfo, 'MysqlI Support => enabled'), 500);
+       if (!preg_match('@Active Persistent Links\s+=>\s+(\d+)@ismU', $phpinfo, $matches))
+               printf("[016] Cannot get # of active persistent links from phpinfo()\n");
+
+       $num_plinks = $matches[1];
+       if ($num_plinks > (int)ini_get('mysqli.max_persistent'))
+               printf("[017] mysqli.max_persistent=%d allows %d open connections!\n", ini_get('mysqli.max_persistent'),$num_plinks);
+
+       mysqli_query($link, 'REVOKE ALL PRIVILEGES, GRANT OPTION FROM pcontest');
+       mysqli_query($link, 'DROP USER pcontest');
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+array(2) {
+  ["id"]=>
+  string(1) "1"
+  ["label"]=>
+  string(1) "a"
+}
+array(2) {
+  ["id"]=>
+  string(1) "1"
+  ["label"]=>
+  string(1) "a"
+}
+
+Warning: mysqli_connect(): Too many open persistent links (%d) in %s on line %d
+done!
+--UEXPECTF--
+array(2) {
+  [u"id"]=>
+  unicode(1) "1"
+  [u"label"]=>
+  unicode(1) "a"
+}
+array(2) {
+  [u"id"]=>
+  unicode(1) "1"
+  [u"label"]=>
+  unicode(1) "a"
+}
+
+Warning: mysqli_connect(): Too many open persistent links (%d) in %s on line %d
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_pconn_reuse.phpt b/ext/mysqli/tests/mysqli_pconn_reuse.phpt
new file mode 100644 (file)
index 0000000..4a7e75b
--- /dev/null
@@ -0,0 +1,92 @@
+--TEST--
+mysqli_pconnect() - reusing/caching persistent connections
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!stristr(mysqli_get_client_info(), 'mysqlnd'))
+       die("skip: only available in mysqlnd");
+?>
+--INI--
+mysqli.allow_persistent=1
+mysqli.max_persistent=2
+mysqli.max_links=2
+--FILE--
+<?php
+       include "connect.inc";
+
+       $host = 'p:' . $host;
+       if (!$link1 = 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, [%d] %s\n",
+                       $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+       }
+       if (!mysqli_query($link1, 'SET @pcondisabled = "Connection 1"'))
+               printf("[002] Cannot set user variable to check if we got the same persistent connection, [%d] %s\n",
+                       mysqli_errno($link1), mysqli_error($link1));
+
+       if (!$link2 = 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, [%d] %s\n",
+                       $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+       }
+
+       if (!$res = mysqli_query($link1, 'SELECT @pcondisabled AS _test'))
+               printf("[004] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       printf("Connection 1 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+       mysqli_free_result($res);
+
+       if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+               printf("[005] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       printf("Connection 2 (no reuse) - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+       $thread_id = mysqli_thread_id($link2);
+       printf("Connection 2 (no reuse) - Thread ID -> '%s'\n", $thread_id);
+       mysqli_free_result($res);
+
+       if (!mysqli_query($link2, 'SET @pcondisabled = "Connection 2"'))
+               printf("[006] Cannot set user variable to check if we got the same persistent connection, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link2));
+
+       if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+               printf("[007] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       printf("Connection 2 - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+       mysqli_free_result($res);
+
+       mysqli_close($link2);
+
+       /* reuse of existing persistent connection expected! */
+       if (!$link2 = 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, [%d] %s\n",
+                       $host, $user, $db, $port, $socket, mysqli_connect_errno(), mysqli_connect_error());
+       }
+
+       if (!$res = mysqli_query($link2, 'SELECT @pcondisabled AS _test'))
+               printf("[009] [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+
+       $row = mysqli_fetch_assoc($res);
+       printf("Connection 2 (reuse) - SELECT @pcondisabled -> '%s'\n", $row['_test']);
+       $thread_id_reuse = mysqli_thread_id($link2);
+       printf("Connection 2 (reuse) - Thread ID -> '%s'\n", $thread_id_reuse);
+       mysqli_free_result($res);
+
+       if ($thread_id != $thread_id_reuse)
+               printf("[010] Seems as if we have got a new connection, connections should have been cached and reused!\n");
+
+       mysqli_close($link1);
+       mysqli_close($link2);
+       print "done!";
+?>
+--EXPECTF--
+Connection 1 - SELECT @pcondisabled -> 'Connection 1'
+Connection 2 (no reuse) - SELECT @pcondisabled -> ''
+Connection 2 (no reuse) - Thread ID -> '%d'
+Connection 2 - SELECT @pcondisabled -> 'Connection 2'
+Connection 2 (reuse) - SELECT @pcondisabled -> 'Connection 2'
+Connection 2 (reuse) - Thread ID -> '%d'
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_query_stored_proc.phpt b/ext/mysqli/tests/mysqli_query_stored_proc.phpt
new file mode 100644 (file)
index 0000000..051b541
--- /dev/null
@@ -0,0 +1,212 @@
+--TEST--
+mysqli_query() - Stored Procedures
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50000) {
+       die(sprintf('skip Needs MySQL 5.0+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[001] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       if (mysqli_query($link, 'CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id, label FROM test ORDER BY id ASC;
+END;')) {
+               /* stored proc which returns one result set */
+               if (mysqli_multi_query($link, 'CALL p()')) {
+                       do {
+                               if ($res = mysqli_use_result($link)) {
+                                       // skip results, don't fetch all from server
+                                       var_dump(mysqli_fetch_assoc($res));
+                                       mysqli_free_result($res);
+                               }
+                       } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+               } else {
+                       printf("[003] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+               }
+
+               if (mysqli_multi_query($link, 'CALL p()')) {
+                       do {
+                               if ($res = mysqli_store_result($link)) {
+                                       // fetch all results from server, but skip on client side
+                                       var_dump(mysqli_fetch_assoc($res));
+                                       mysqli_free_result($res);
+                               }
+                       } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+               } else {
+                       printf("[004] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+               }
+
+               if (mysqli_multi_query($link, 'CALL p()')) {
+                       do {
+                               if ($res = mysqli_store_result($link)) {
+                                       // fetch all results from server, but skip on client side
+                                       var_dump(mysqli_fetch_assoc($res));
+                                       while (mysqli_fetch_assoc($res))
+                                               ;
+                                       mysqli_free_result($res);
+                               }
+                       } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+               } else {
+                       printf("[005] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+               }
+
+       } else {
+               printf("[002] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[006] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       if (mysqli_query($link, 'CREATE PROCEDURE p() READS SQL DATA BEGIN SELECT id, label FROM test ORDER BY id ASC; SELECT id FROM test ORDER BY id ASC; END;')) {
+               /* stored proc which returns two result sets */
+
+               if (mysqli_multi_query($link, 'CALL p()')) {
+                       do {
+                               if ($res = mysqli_store_result($link)) {
+                                       // fetch all results from server, but skip on client side
+                                       var_dump(mysqli_fetch_assoc($res));
+                                       mysqli_free_result($res);
+                               }
+                       } while (mysqli_more_results($link) && mysqli_next_result($link));
+
+               } else {
+                       printf("[008] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+               }
+
+       } else {
+               printf("[007] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[009] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+               /* no result set, just output parameter */
+               if (!mysqli_query($link, 'CALL p(@version)'))
+                       printf("[011] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_query($link, 'SET @version = "unknown"'))
+                       printf("[012] Cannot reset user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_query($link, 'CALL p(@version)'))
+                       printf("[013] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!$res = mysqli_query($link, 'SELECT @version as _vers'))
+                       printf("[014] Cannot fetch user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!$row = mysqli_fetch_assoc($res) ||
+                               $row['_vers'] == 'unknown')
+                       printf("[015] Results seem wrong, got %s, [%d] %s\n",
+                               $row['_vers'],
+                               mysqli_errno($link), mysqli_error($link));
+               mysqli_free_result($res);
+
+       } else {
+               printf("[010] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[016] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       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;')) {
+               /* no result set, one input, one output parameter */
+               if (!mysqli_query($link, 'CALL p("myversion", @version)'))
+                       printf("[018] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_query($link, 'SET @version = "unknown"'))
+                       printf("[019] Cannot reset user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_query($link, 'CALL p("myversion", @version)'))
+                       printf("[020] Cannot call SP, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!$res = mysqli_query($link, 'SELECT @version as _vers'))
+                       printf("[021] Cannot fetch user variable, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!$row = mysqli_fetch_assoc($res) ||
+                               $row['_vers'] == 'myversion')
+                       printf("[022] Results seem wrong, got %s, [%d] %s\n",
+                               $row['_vers'],
+                               mysqli_errno($link), mysqli_error($link));
+               mysqli_free_result($res);
+
+       } else {
+               printf("[017] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+array(2) {
+  ["id"]=>
+  string(1) "1"
+  ["label"]=>
+  string(1) "a"
+}
+array(2) {
+  ["id"]=>
+  string(1) "1"
+  ["label"]=>
+  string(1) "a"
+}
+array(2) {
+  ["id"]=>
+  string(1) "1"
+  ["label"]=>
+  string(1) "a"
+}
+array(2) {
+  ["id"]=>
+  string(1) "1"
+  ["label"]=>
+  string(1) "a"
+}
+array(1) {
+  ["id"]=>
+  string(1) "1"
+}
+done!
+--UEXPECTF--
+array(2) {
+  [u"id"]=>
+  unicode(1) "1"
+  [u"label"]=>
+  unicode(1) "a"
+}
+array(2) {
+  [u"id"]=>
+  unicode(1) "1"
+  [u"label"]=>
+  unicode(1) "a"
+}
+array(2) {
+  [u"id"]=>
+  unicode(1) "1"
+  [u"label"]=>
+  unicode(1) "a"
+}
+array(2) {
+  [u"id"]=>
+  unicode(1) "1"
+  [u"label"]=>
+  unicode(1) "a"
+}
+array(1) {
+  [u"id"]=>
+  unicode(1) "1"
+}
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_big5.phpt b/ext/mysqli/tests/mysqli_real_escape_string_big5.phpt
new file mode 100644 (file)
index 0000000..ea49205
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+mysqli_real_escape_string() - big5
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+       die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+               mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'big5'))
+       die(sprintf("skip Cannot set charset 'big5'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       var_dump(mysqli_set_charset($link, "big5"));
+
+       if ('§ä¨ì¥H¤U¤º®e\\\\§ä¨ì¥H¤U¤º®e' !== ($tmp = mysqli_real_escape_string($link, '§ä¨ì¥H¤U¤º®e\\§ä¨ì¥H¤U¤º®e')))
+               printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+       if ('§ä¨ì¥H¤U¤º®e\"§ä¨ì¥H¤U¤º®e' !== ($tmp = mysqli_real_escape_string($link, '§ä¨ì¥H¤U¤º®e"§ä¨ì¥H¤U¤º®e')))
+               printf("[005] Expecting \", got %s\n", $tmp);
+
+       if ("§ä¨ì¥H¤U¤º®e\'§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link, "§ä¨ì¥H¤U¤º®e'§ä¨ì¥H¤U¤º®e")))
+               printf("[006] Expecting ', got %s\n", $tmp);
+
+       if ("§ä¨ì¥H¤U¤º®e\\n§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link, "§ä¨ì¥H¤U¤º®e\n§ä¨ì¥H¤U¤º®e")))
+               printf("[007] Expecting \\n, got %s\n", $tmp);
+
+       if ("§ä¨ì¥H¤U¤º®e\\r§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link, "§ä¨ì¥H¤U¤º®e\r§ä¨ì¥H¤U¤º®e")))
+               printf("[008] Expecting \\r, got %s\n", $tmp);
+
+       if ("§ä¨ì¥H¤U¤º®e\\0§ä¨ì¥H¤U¤º®e" !== ($tmp = mysqli_real_escape_string($link, "§ä¨ì¥H¤U¤º®e" . chr(0) . "§ä¨ì¥H¤U¤º®e")))
+               printf("[009] Expecting %s, got %s\n", "§ä¨ì¥H¤U¤º®e\\0§ä¨ì¥H¤U¤º®e", $tmp);
+
+       var_dump(mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "§ä")'));
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt b/ext/mysqli/tests/mysqli_real_escape_string_eucjpms.phpt
new file mode 100644 (file)
index 0000000..ef9c3f0
--- /dev/null
@@ -0,0 +1,53 @@
+--TEST--
+mysqli_real_escape_string() - eucjpms
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+       die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+               mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'eucjpms'))
+       die(sprintf("skip Cannot set charset 'eucjpms'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       var_dump(mysqli_set_charset($link, "eucjpms"));
+
+       if ('¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\\\¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï' !== ($tmp = mysqli_real_escape_string($link, '¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï')))
+               printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+       if ('¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\"¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï' !== ($tmp = mysqli_real_escape_string($link, '¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï"¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï')))
+               printf("[005] Expecting \", got %s\n", $tmp);
+
+       if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\'¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï'¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+               printf("[006] Expecting ', got %s\n", $tmp);
+
+       if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\n¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\n¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+               printf("[007] Expecting \\n, got %s\n", $tmp);
+
+       if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\r¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\r¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+               printf("[008] Expecting \\r, got %s\n", $tmp);
+
+       if ("¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\0¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" !== ($tmp = mysqli_real_escape_string($link, "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï" . chr(0) . "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï")))
+               printf("[009] Expecting %s, got %s\n", "¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï\\0¤³¤ÎÁȤ߹ç¤ï¤»¤Ç¤Ï", $tmp);
+
+       var_dump(mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "¤³")'));
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt b/ext/mysqli/tests/mysqli_real_escape_string_euckr.phpt
new file mode 100644 (file)
index 0000000..a15a51c
--- /dev/null
@@ -0,0 +1,53 @@
+--TEST--
+mysqli_real_escape_string() - euckr
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+       die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+               mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'euckr'))
+       die(sprintf("skip Cannot set charset 'euckr'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       var_dump(mysqli_set_charset($link, "euckr"));
+
+       if ('±Ç´ë¼º\\\\±Ç´ë¼º' !== ($tmp = mysqli_real_escape_string($link, '±Ç´ë¼º\\±Ç´ë¼º')))
+               printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+       if ('±Ç´ë¼º\"±Ç´ë¼º' !== ($tmp = mysqli_real_escape_string($link, '±Ç´ë¼º"±Ç´ë¼º')))
+               printf("[005] Expecting \", got %s\n", $tmp);
+
+       if ("±Ç´ë¼º\'±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º'±Ç´ë¼º")))
+               printf("[006] Expecting ', got %s\n", $tmp);
+
+       if ("±Ç´ë¼º\\n±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º\n±Ç´ë¼º")))
+               printf("[007] Expecting \\n, got %s\n", $tmp);
+
+       if ("±Ç´ë¼º\\r±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º\r±Ç´ë¼º")))
+               printf("[008] Expecting \\r, got %s\n", $tmp);
+
+       if ("±Ç´ë¼º\\0±Ç´ë¼º" !== ($tmp = mysqli_real_escape_string($link, "±Ç´ë¼º" . chr(0) . "±Ç´ë¼º")))
+               printf("[009] Expecting %s, got %s\n", "±Ç´ë¼º\\0±Ç´ë¼º", $tmp);
+
+       var_dump(mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "±Ç")'));
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt b/ext/mysqli/tests/mysqli_real_escape_string_gb2312.phpt
new file mode 100644 (file)
index 0000000..016115f
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+mysqli_real_escape_string() - gb2312
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+       die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+               mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'gb2312'))
+       die(sprintf("skip Cannot set charset 'gb2312'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       var_dump(mysqli_set_charset($link, "gb2312"));
+
+       if ('Ê×ÏÈ\\\\Ê×ÏÈ' !== ($tmp = mysqli_real_escape_string($link, 'Ê×ÏÈ\\Ê×ÏÈ')))
+               printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+       if ('Ê×ÏÈ\"Ê×ÏÈ' !== ($tmp = mysqli_real_escape_string($link, 'Ê×ÏÈ"Ê×ÏÈ')))
+               printf("[005] Expecting \", got %s\n", $tmp);
+
+       if ("Ê×ÏÈ\'Ê×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ'Ê×ÏÈ")))
+               printf("[006] Expecting ', got %s\n", $tmp);
+
+       if ("Ê×ÏÈ\\nÊ×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ\nÊ×ÏÈ")))
+               printf("[007] Expecting \\n, got %s\n", $tmp);
+
+       if ("Ê×ÏÈ\\rÊ×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ\rÊ×ÏÈ")))
+               printf("[008] Expecting \\r, got %s\n", $tmp);
+
+       if ("Ê×ÏÈ\\0Ê×ÏÈ" !== ($tmp = mysqli_real_escape_string($link, "Ê×ÏÈ" . chr(0) . "Ê×ÏÈ")))
+               printf("[009] Expecting %s, got %s\n", "Ê×ÏÈ\\0Ê×ÏÈ", $tmp);
+
+       var_dump(mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "Ê×")'));
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt b/ext/mysqli/tests/mysqli_real_escape_string_gbk.phpt
new file mode 100644 (file)
index 0000000..bee717f
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+mysqli_real_escape_string() - gbk
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+       die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+               mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'gbk'))
+       die(sprintf("skip Cannot set charset 'gbk'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       var_dump(mysqli_set_charset($link, "gbk"));
+
+       if ('�İ汾\\\\�İ汾' !== ($tmp = mysqli_real_escape_string($link, '�İ汾\\�İ汾')))
+               printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+       if ('�İ汾\"�İ汾' !== ($tmp = mysqli_real_escape_string($link, '�İ汾"�İ汾')))
+               printf("[005] Expecting \", got %s\n", $tmp);
+
+       if ("�İ汾\'�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾'�İ汾")))
+               printf("[006] Expecting ', got %s\n", $tmp);
+
+       if ("�İ汾\\n�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾\n�İ汾")))
+               printf("[007] Expecting \\n, got %s\n", $tmp);
+
+       if ("�İ汾\\r�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾\r�İ汾")))
+               printf("[008] Expecting \\r, got %s\n", $tmp);
+
+       if ("�İ汾\\0�İ汾" !== ($tmp = mysqli_real_escape_string($link, "�İ汾" . chr(0) . "�İ汾")))
+               printf("[009] Expecting %s, got %s\n", "�İ汾\\0�İ汾", $tmp);
+
+       var_dump(mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "��")'));
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt b/ext/mysqli/tests/mysqli_real_escape_string_nobackslash.phpt
new file mode 100644 (file)
index 0000000..bdbcc19
--- /dev/null
@@ -0,0 +1,71 @@
+--TEST--
+mysqli_real_escape_string() - SQL Mode NO_BACKSLASH_ESCAPE
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       if (!mysqli_query($link, 'SET @@sql_mode="NO_BACKSLASH_ESCAPES"'))
+               printf("[001] Cannot set NO_BACKSLASH_ESCAPES, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ('\\' !== ($tmp = mysqli_real_escape_string($link, '\\')))
+               printf("[002] Expecting \\, got %s\n", $tmp);
+
+       if ('"' !== ($tmp = mysqli_real_escape_string($link, '"')))
+               printf("[003] Expecting \", got %s\n", $tmp);
+
+       if ("''" !== ($tmp = mysqli_real_escape_string($link, "'")))
+               printf("[004] Expecting '', got %s\n", $tmp);
+
+       if ("\n" !== ($tmp = mysqli_real_escape_string($link, "\n")))
+               printf("[005] Expecting \\n, got %s\n", $tmp);
+
+       if ("\r" !== ($tmp = mysqli_real_escape_string($link, "\r")))
+               printf("[006] Expecting \\r, got %s\n", $tmp);
+
+       assert("foo" . chr(0) . "bar" === "foo" . chr(0) . "bar");
+       if ("foo" . chr(0) . "bar" !== ($tmp = mysqli_real_escape_string($link, "foo" . chr(0) . "bar")))
+               printf("[007] Expecting %s, got %s\n", "foo" . chr(0) . "bar", $tmp);
+
+       if (!mysqli_query($link, sprintf('INSERT INTO test(id, label) VALUES (100, "%s")',
+                       mysqli_real_escape_string($link, "\\"))))
+               printf("[009] Cannot INSERT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!($res = mysqli_query($link, 'SELECT label FROM test WHERE id = 100')) ||
+                       !($row = mysqli_fetch_assoc($res)))
+               printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       var_dump($row);
+       mysqli_free_result($res);
+
+       if (!mysqli_query($link, 'SET @@sql_mode=""'))
+               printf("[011] Cannot disable NO_BACKSLASH_ESCAPES, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if ('\\\\' !== ($tmp = mysqli_real_escape_string($link, '\\')))
+               printf("[012] Expecting \\, got %s\n", $tmp);
+
+       if ("foo\\0bar" !== ($tmp = mysqli_real_escape_string($link, "foo" . chr(0) . "bar")))
+               printf("[013] Expecting %s, got %s\n", "foo" . chr(0) . "bar", $tmp);
+
+       mysqli_close($link);
+
+       print "done!";
+?>
+--EXPECTF--
+array(1) {
+  ["label"]=>
+  string(1) "\"
+}
+done!
+--UEXPECTF--
+array(1) {
+  [u"label"]=>
+  unicode(1) "\"
+}
+done!
diff --git a/ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt b/ext/mysqli/tests/mysqli_real_escape_string_sjis.phpt
new file mode 100644 (file)
index 0000000..7655ecd
--- /dev/null
@@ -0,0 +1,54 @@
+--TEST--
+mysqli_real_escape_string() - sjis
+--SKIPIF--
+<?php
+if (ini_get('unicode.semantics'))
+       die("skip Test cannot be run in unicode mode");
+
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('connect.inc');
+
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf("skip Cannot connect to MySQL, [%d] %s\n",
+               mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (!mysqli_set_charset($link, 'sjis'))
+       die(sprintf("skip Cannot set charset 'sjis'"));
+mysqli_close($link);
+?>
+--FILE--
+<?php
+
+       require_once("connect.inc");
+       require_once('table.inc');
+
+       var_dump(mysqli_set_charset($link, "sjis"));
+
+       if ('?p??\\\\?p??' !== ($tmp = mysqli_real_escape_string($link, '?p??\\?p??')))
+               printf("[004] Expecting \\\\, got %s\n", $tmp);
+
+       if ('?p??\"?p??' !== ($tmp = mysqli_real_escape_string($link, '?p??"?p??')))
+               printf("[005] Expecting \", got %s\n", $tmp);
+
+       if ("?p??\'?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??'?p??")))
+               printf("[006] Expecting ', got %s\n", $tmp);
+
+       if ("?p??\\n?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??\n?p??")))
+               printf("[007] Expecting \\n, got %s\n", $tmp);
+
+       if ("?p??\\r?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??\r?p??")))
+               printf("[008] Expecting \\r, got %s\n", $tmp);
+
+       if ("?p??\\0?p??" !== ($tmp = mysqli_real_escape_string($link, "?p??" . chr(0) . "?p??")))
+               printf("[009] Expecting %s, got %s\n", "?p??\\0?p??", $tmp);
+
+       var_dump(mysqli_query($link, 'INSERT INTO test(id, label) VALUES (100, "?p")'));
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_reconnect.phpt b/ext/mysqli/tests/mysqli_reconnect.phpt
new file mode 100644 (file)
index 0000000..68cffc3
--- /dev/null
@@ -0,0 +1,130 @@
+--TEST--
+Trying implicit reconnect after wait_timeout and KILL using mysqli_ping()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (stristr(mysqli_get_client_info(), 'mysqlnd'))
+       die("skip: test for libmysql");
+?>
+--INI--
+mysqli.reconnect=1
+--FILE--
+<?php
+       require_once("connect.inc");
+       require_once("table.inc");
+
+       if (!$link2 = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] Cannot create second database connection, [%d] %s\n",
+                       mysqli_connect_errno(), mysqli_connect_error());
+
+       $thread_id_timeout = mysqli_thread_id($link);
+       $thread_id_control = mysqli_thread_id($link2);
+
+       if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+               printf("[002] Cannot get full processlist, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (!isset($running_threads[$thread_id_timeout]) ||
+                       !isset($running_threads[$thread_id_control]))
+               printf("[003] Processlist is borked, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       if (!mysqli_query($link, "SET SESSION wait_timeout = 2"))
+               printf("[004] Cannot set wait_timeout, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (!$res = mysqli_query($link, "SHOW VARIABLES LIKE 'wait_timeout'"))
+               printf("[005] Cannot check if wait_timeout has been set, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[006] Cannot get wait_timeout, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+       mysqli_free_result($res);
+
+       if ($row['Value'] != 2)
+               printf("[007] Failed setting the wait_timeout, test will not work, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       // after 2+ seconds the server should kill the connection
+       sleep(3);
+
+       if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+               printf("[008] Cannot get full processlist, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (isset($running_threads[$thread_id_timeout]))
+               printf("[009] Server should have killed the timeout connection, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       if (true !== mysqli_ping($link))
+               printf("[010] Reconnect should have happened");
+
+       if (!$res = mysqli_query($link, "SELECT DATABASE() as _dbname"))
+               printf("[011] Cannot get database name, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[012] Cannot get database name, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res);
+       if ($row['_dbname'] != $db)
+               printf("[013] Connection should has been made to DB/Schema '%s', expecting '%s', [%d] %s\n",
+                       $row['_dbname'], $db, mysqli_errno($link), mysqli_error($link));
+
+       // ... and now we try KILL
+       $thread_id_timeout = mysqli_thread_id($link);
+
+       if (!mysqli_query($link2, sprintf('KILL %d', $thread_id_timeout)))
+               printf("[014] Cannot KILL timeout connection, [%d] %s\n", mysqli_errno($link2), mysqli_error($link2));
+       // Give the server a second to really kill the other thread...
+       sleep(1);
+
+       if (!$res = mysqli_query($link2, "SHOW FULL PROCESSLIST"))
+               printf("[015] Cannot get full processlist, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       $running_threads = array();
+       while ($row = mysqli_fetch_assoc($res))
+               $running_threads[$row['Id']] = $row;
+       mysqli_free_result($res);
+
+       if (isset($running_threads[$thread_id_timeout]) ||
+                       !isset($running_threads[$thread_id_control]))
+               printf("[016] Processlist is borked, [%d] %s\n",
+                       mysqli_errno($link2), mysqli_error($link));
+
+       if (true !== ($tmp = mysqli_ping($link)))
+               printf("[017] Expecting boolean/true got %s/%s\n", gettype($tmp), $tmp);
+
+       if (!$res = mysqli_query($link, "SELECT DATABASE() as _dbname"))
+               printf("[018] Cannot get database name, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       if (!$row = mysqli_fetch_assoc($res))
+               printf("[019] Cannot get database name, [%d] %s\n",
+                       mysqli_errno($link), mysqli_error($link));
+
+       mysqli_free_result($res);
+       if ($row['_dbname'] != $db)
+               printf("[020] Connection should has been made to DB/Schema '%s', expecting '%s', [%d] %s\n",
+                       $row['_dbname'], $db, mysqli_errno($link), mysqli_error($link));
+
+       mysqli_close($link);
+       mysqli_close($link2);
+       print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt
new file mode 100644 (file)
index 0000000..a4f20cb
--- /dev/null
@@ -0,0 +1,110 @@
+--TEST--
+mysqli_set_local_infile_handler() - open basedir restrictions
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+       die("skip - function not available.");
+
+require_once('connect.inc');
+if (!$link = mysqli_connect($host, $user, $passwb, $db, $port, $socket))
+       die("skip Cannot connect to MySQL");
+
+if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "local_infile"')) {
+       mysqli_close($link);
+       die("skip Cannot check if Server variable 'local_infile' is set to 'ON'");
+}
+
+$row = mysqli_fetch_assoc($res);
+mysqli_free_result($res);
+mysqli_close($link);
+
+if ('ON' != $row['Value'])
+       die(sprintf("skip Server variable 'local_infile' seems not set to 'ON', found '%s'",
+               $row['Value']));
+?>
+--INI--
+open_basedir="."
+--FILE--
+<?php
+       @include('connect.inc');
+       if (!isset($db)) {
+               // stupid run-tests.php - any idea how to set system ini setting dynamically???
+               print "Warning: tempnam(): open_basedir restriction in effect. File(grrr) is not within the allowed path(s): (grrr) in grrr on line 0
+[005 + 1] Cannot create CVS file ''
+Callback set to 'callback_simple'
+[012] LOAD DATA failed, [0] grrr
+[014/0] [0] ''
+done!";
+               die();
+       }
+
+       require_once('connect.inc');
+       require_once('local_infile_tools.inc');
+       require_once('table.inc');
+
+       function callback_simple($fp, &$buffer, $buflen, &$error) {
+               static $invocation = 0;
+
+               printf("Callback: %d\n", $invocation);
+
+               $invocation++;
+               if (!is_resource($fp))
+                       printf("[012] First argument passed to callback is not a resource but %s/%s\n",
+                               $fp, gettype($fp));
+
+               if (!$buffer = fread($fp, $buflen)) {
+                       if ($invocation == 1) {
+                               printf("[013] Cannot read from stream\n");
+                                       $error = 'Cannot read from stream';
+                       } else {
+                               return strlen($buffer);
+                       }
+               }
+
+               $lines = explode("\n", $buffer);
+               if (count($lines) != 4 && strlen($buffer) > 0) {
+                       printf("[014] Test is too simple to handle a buffer of size %d that cannot hold all lines\n", $buflen);
+                       $error = 'Parser too simple';
+               }
+
+               $buffer = '';
+               foreach ($lines as $k => $line) {
+                       if ('' === trim($line))
+                               continue;
+
+                       $columns = explode(';', $line);
+                       if (empty($columns)) {
+                               printf("[015] Cannot parse columns\n");
+                               $error = 'Cannot parse columns';
+                       }
+
+                       // increase id column value
+                       $columns[0] += 1;
+                       $buffer .= implode(';', $columns);
+                       $buffer .= "\n";
+               }
+
+               return strlen($buffer);
+       }
+
+       $file = create_standard_csv(5);
+       $expected = array(
+               array('id' => 98,   'label' => 'x'),
+               array('id' => 99,   'label' => 'y'),
+               array('id' => 100,  'label' => 'z'),
+       );
+       try_handler(10, $link, $file, 'callback_simple', $expected);
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+Warning: tempnam(): open_basedir restriction in effect. File(%s) is not within the allowed path(s): (%s) in %s on line %d
+[005 + 1] Cannot create CVS file ''
+Callback set to 'callback_simple'
+[012] LOAD DATA failed, [%d] %s
+[014/0] [0] ''
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt
new file mode 100644 (file)
index 0000000..ba88686
--- /dev/null
@@ -0,0 +1,333 @@
+--TEST--
+Playing with SELECT FORMAT(...) AS _format - see also bugs.php.net/42378
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--INI--
+memory_limit=83886080
+--FILE--
+<?php
+       require_once("connect.inc");
+
+       function create_table($link, $column, $min, $max, $engine, $offset) {
+
+               if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) {
+                       printf("[%03d] Cannot drop table test, [%d] %s\n",
+                               $offset,
+                               mysqli_errno($link), mysqli_error($link));
+                       return array();
+               }
+
+               $sql = sprintf("CREATE TABLE test(id INT AUTO_INCREMENT PRIMARY KEY, col1 %s) ENGINE=%s",
+                       $column, $engine);
+               if (!mysqli_query($link, $sql)) {
+                       printf("[%03d] Cannot create table test, [%d] %s\n",
+                               $offset + 1,
+                               mysqli_errno($link), mysqli_error($link));
+                       return array();
+               }
+
+               $values = array();
+               for ($i = 1; $i <= 100; $i++) {
+                       $col1 = mt_rand($min, $max);
+                       $values[$i] = $col1;
+                       $sql = sprintf("INSERT INTO test(id, col1) VALUES (%d, %f)",
+                               $i, $col1);
+                       if (!mysqli_query($link, $sql)) {
+                               printf("[%03d] Cannot insert data, [%d] %s\n",
+                                       $offset + 2,
+                                       mysqli_errno($link), mysqli_error($link));
+                               return array();
+                       }
+               }
+
+               return $values;
+       }
+
+       function test_format($link, $format, $from, $order_by, $expected, $offset) {
+
+               if (!$stmt = mysqli_stmt_init($link)) {
+                       printf("[%03d] Cannot create PS, [%d] %s\n",
+                               $offset,
+                               mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               if ($order_by)
+                       $sql = sprintf('SELECT %s AS _format FROM %s ORDER BY %s', $format, $from, $order_by);
+               else
+                       $sql = sprintf('SELECT %s AS _format FROM %s', $format, $from);
+
+               if (!mysqli_stmt_prepare($stmt, $sql)) {
+                       printf("[%03d] Cannot prepare PS, [%d] %s\n",
+                               $offset + 1,
+                               mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       return false;
+               }
+
+               if (!mysqli_stmt_execute($stmt)) {
+                       printf("[%03d] Cannot execute PS, [%d] %s\n",
+                               $offset + 2,
+                               mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       return false;
+               }
+
+               if (!mysqli_stmt_store_result($stmt)) {
+                       printf("[%03d] Cannot store result set, [%d] %s\n",
+                               $offset + 3,
+                               mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       return false;
+               }
+
+               if (!is_array($expected)) {
+
+                       $result = null;
+                       if (!mysqli_stmt_bind_result($stmt, $result)) {
+                               printf("[%03d] Cannot bind result, [%d] %s\n",
+                                       $offset + 4,
+                                       mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                               return false;
+                       }
+
+                       if (!mysqli_stmt_fetch($stmt)) {
+                               printf("[%03d] Cannot fetch result,, [%d] %s\n",
+                                       $offset + 5,
+                                       mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                               return false;
+                       }
+
+                       if ($result !== $expected) {
+                               printf("[%03d] Expecting %s/%s got %s/%s with %s - %s.\n",
+                                       $offset + 6,
+                                       gettype($expected), $expected,
+                                       gettype($result), $result,
+                                       $format, $sql);
+                       }
+
+               } else {
+
+                       $order_by_col = $result = null;
+                       if (!mysqli_stmt_bind_result($stmt, $order_by_col, $result)) {
+                               printf("[%03d] Cannot bind result, [%d] %s\n",
+                                       $offset + 7,
+                                       mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                               return false;
+                       }
+
+                       reset($expected);
+                       while ((list($k, $v) = each($expected)) && mysqli_stmt_fetch($stmt)) {
+                               if ($result !== $v) {
+                                       printf("[%03d] Row %d - expecting %s/%s got %s/%s [%s] with %s - %s.\n",
+                                               $offset + 8,
+                                               $k,
+                                               gettype($v), $v,
+                                               gettype($result), $result,
+                                               $order_by_col,
+                                               $format, $sql);
+                               }
+                       }
+
+               }
+
+               mysqli_stmt_free_result($stmt);
+               mysqli_stmt_close($stmt);
+
+               return true;
+       }
+
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] Cannot connect - [%d] %s\n",
+                       mysqli_connect_errno(),
+                       mysqli_connect_error());
+
+       /* select from dual - pseudo table */
+       test_format($link, 'FORMAT(1.01, 0)', 'DUAL', null, '1', 10);
+       test_format($link, 'FORMAT(1.23, 1)', 'DUAL', null, '1.2', 20);
+       test_format($link, 'FORMAT(1.23, 2)', 'DUAL', null, '1.23', 30);
+       test_format($link, 'FORMAT(1234.567, 3)', 'DUAL', null, '1,234.567', 40);
+       /* no typo! */
+       test_format($link, 'FORMAT(1234.567, 4)', 'DUAL', null, '1,234.5670', 50);
+
+       mysqli_close($link);
+       require_once('table.inc');
+
+       /* select from existing table */
+       test_format($link, 'FORMAT(id, 0)', 'test', null, '1', 60);
+       test_format($link, 'FORMAT(id + 0.1, 1)', 'test', null, '1.1', 70);
+       test_format($link, 'FORMAT(id + 0.01, 2)', 'test', null, '1.01', 80);
+
+       /* create new table and select from it */
+       $expected = create_table($link, 'FLOAT', -10000, 10000, $engine, 90);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 100);
+
+       $expected = create_table($link, 'FLOAT UNSIGNED', 0, 10000, $engine, 110);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 120);
+
+       $expected = create_table($link, 'TINYINT', -128, 127, $engine, 130);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 140);
+
+       $expected = create_table($link, 'SMALLINT UNSIGNED', 0, 65535, $engine, 150);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 160);
+
+       $expected = create_table($link, 'MEDIUMINT', 0, 8388607, $engine, 170);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 180);
+
+       $expected = create_table($link, 'INT UNSIGNED', 0, 1000, $engine, 190);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 200);
+
+       $expected = create_table($link, 'BIGINT', -1000, 1000, $engine, 210);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 220);
+
+       $expected = create_table($link, 'DECIMAL(5,0)', -1000, 1000, $engine, 230);
+       foreach ($expected as $k => $v)
+               $expected[$k] = number_format(round($v), 0, '.', ',');
+       test_format($link, 'id AS order_by_col, FORMAT(col1, 0)', 'test', 'id', $expected, 240);
+
+       // http://bugs.php.net/bug.php?id=42378
+       if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+               printf("[300] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       if (mysqli_query($link, "CREATE TABLE `test` (
+  `targetport` int(11) NOT NULL default '0',
+  `sources` double(17,4) default NULL,
+  `current_sources` double(17,0) default NULL,
+  `reports` double(17,4) default NULL,
+  `current_reports` double(17,0) default NULL,
+  `targets` double(17,4) default NULL,
+  `current_targets` double(17,0) default NULL,
+  `maxsources` int(11) default NULL,
+  `maxtargets` int(11) default NULL,
+  `maxreports` int(11) default NULL,
+  `trend` float default NULL,
+  PRIMARY KEY  (`targetport`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1")) {
+
+               do {
+                       $values = array();
+                       for ($i = 0; $i < 200; $i++) {
+                               $current_targets = mt_rand(-100000, 100000) / 10;
+                               do {
+                                       $trend = (mt_rand(0, 3) > 1) ? (mt_rand(-10000, 10000) / 100) : 'NULL';
+                               } while (isset($values[$trend]));
+
+                               $sql = sprintf('INSERT INTO test(targetport, current_targets, maxreports, trend) VALUES (%d, %f, %s, %s)',
+                                       $i,
+                                       $current_targets,
+                                       (mt_rand(0, 1) > 0) ? mt_rand(0, 1000) : 'NULL',
+                                       $trend);
+                               if (!mysqli_query($link, $sql)) {
+                                       printf("[301] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+                                       break 2;
+                               }
+                               if ($current_targets > 0 && $trend != 'NULL')
+                                       $values[$trend] = $i;
+                       }
+                       krsort($values);
+
+                       if (!$stmt = mysqli_stmt_init($link)) {
+                               printf("[302] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+                               break;
+                       }
+
+                       if (!mysqli_stmt_prepare($stmt, 'SELECT trend, targetport, FORMAT(trend, 2) FROM test WHERE current_targets > 0 AND trend IS NOT NULL ORDER BY trend DESC LIMIT 100')) {
+                               printf("[303] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       if (!mysqli_stmt_execute($stmt)) {
+                               printf("[304] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       if (!mysqli_stmt_store_result($stmt)) {
+                               printf("[305] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       $trend = $targetport = $format = null;
+                       if (!mysqli_stmt_bind_result($stmt, $trend, $targetport, $format)) {
+
+                               printf("[305] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       reset($values);
+                       while (mysqli_stmt_fetch($stmt)) {
+                               list($exp_trend, $exp_targetport) = each($values);
+                               if ($targetport != $exp_targetport) {
+                                       printf("[306] Values fetched from MySQL seem to be wrong, check manually\n");
+                                       printf("%s/%s - %s/%s - '%s'\n", $trend, $exp_trend, $targetport, $exp_targetport, $format);
+                               }
+                       }
+                       mysqli_stmt_free_result($stmt);
+                       mysqli_stmt_close($stmt);
+
+                       // same but OO interface
+                       if (!$stmt = mysqli_stmt_init($link)) {
+                               printf("[307] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+                               break;
+                       }
+
+                       if (!$stmt->prepare('SELECT trend, targetport, FORMAT(trend, 2) FROM test WHERE current_targets > 0 AND trend IS NOT NULL ORDER BY trend DESC LIMIT 100')) {
+                               printf("[308] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       if (!$stmt->execute()) {
+                               printf("[309] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       if (!$stmt->store_result()) {
+                               printf("[310] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       $trend = $targetport = $format = null;
+                       if (!$stmt->bind_result($trend, $targetport, $format)) {
+
+                               printf("[311] [%d] %s\n", mysqli_stmt_errno($link), mysqli_stmt_error($link));
+                               break;
+                       }
+
+                       reset($values);
+                       while ($stmt->fetch()) {
+                               list($exp_trend, $exp_targetport) = each($values);
+                               if ($targetport != $exp_targetport) {
+                                       printf("[312] Values fetched from MySQL seem to be wrong, check manually\n");
+                                       printf("%s/%s - %s/%s - '%s'\n", $trend, $exp_trend, $targetport, $exp_targetport, $format);
+                               }
+                       }
+                       $stmt->free_result();
+                       $stmt->close();
+
+               } while (false);
+
+       } else {
+               var_dump(mysqli_error($link));
+       }
+
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt
new file mode 100644 (file)
index 0000000..f6b7444
--- /dev/null
@@ -0,0 +1,185 @@
+--TEST--
+mysqli_stmt_execute() - Stored Procedures
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+       die(sprintf('skip Cannot connect to MySQL, [%d] %s.', mysqli_connect_errno(), mysqli_connect_error()));
+}
+if (mysqli_get_server_version($link) <= 50000) {
+       die(sprintf('skip Needs MySQL 5.0+, found version %d.', mysqli_get_server_version($link)));
+}
+?>
+--FILE--
+<?php
+       require_once('connect.inc');
+       require_once('table.inc');
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[009] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+               /* no result set, one output parameter */
+               if (!$stmt = mysqli_prepare($link, 'CALL p(@version)'))
+                       printf("[011] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[012] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               /* yes, I really want to call it twice! */
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[013] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!mysqli_stmt_close($stmt))
+                       printf("[014] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+                       printf("[015] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[016] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               $version = 'unknown';
+               if (!mysqli_stmt_bind_result($stmt, $version) ||
+                               !mysqli_stmt_fetch($stmt))
+                       printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (($version == "unknown") || ($version == ""))
+                       printf("[018] Results seem wrong, got %s, [%d] %s\n",
+                               $version,
+                               mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               mysqli_stmt_free_result($stmt);
+               mysqli_stmt_close($stmt);
+
+       } else {
+               printf("[010] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+
+       if (function_exists('mysqli_stmt_get_result')) {
+
+               if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+                       printf("[019] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+               if (mysqli_real_query($link, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;')) {
+                       // no result set, one output parameter
+                       if (!$stmt = mysqli_prepare($link, 'CALL p(@version)'))
+                               printf("[020] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+                       if (!mysqli_stmt_execute($stmt))
+                               printf("[021] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+                       if (!mysqli_stmt_close($stmt))
+                               printf("[022] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+                       if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+                               printf("[023] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+                       if (!mysqli_stmt_execute($stmt))
+                               printf("[024] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+                       if (!$res = mysqli_stmt_get_result($stmt))
+                               printf("[025] Cannot get result set, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+                       if ((!($row = mysqli_fetch_assoc($res))) || ($row['_version'] == ""))
+                               printf("[026] Results seem wrong, got %s, [%d] %s\n",
+                                       $row['_version'],
+                                       mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+                       mysqli_free_result($res);
+                       mysqli_stmt_close($stmt);
+
+               } else {
+                       printf("[027] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+               }
+
+       }
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[028] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       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;')) {
+               // no result set, one input parameter, output parameter
+               // yes, I really do not want to bind input values...
+               if (!$stmt = mysqli_prepare($link, 'CALL p("myversion", @version)'))
+                       printf("[029] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[030] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!mysqli_stmt_close($stmt))
+                       printf("[031] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+                       printf("[032] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[033] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               $version = 'unknown';
+               if (!mysqli_stmt_bind_result($stmt, $version) ||
+                               !mysqli_stmt_fetch($stmt))
+                       printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if ($version != "myversion")
+                       printf("[035] Results seem wrong, got %s, [%d] %s\n",
+                               $version,
+                               mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               mysqli_stmt_free_result($stmt);
+               mysqli_stmt_close($stmt);
+
+       } else {
+               printf("[036] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       if (!mysqli_query($link, 'DROP PROCEDURE IF EXISTS p'))
+               printf("[037] [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+
+       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;')) {
+               // no result set, one input parameter, output parameter
+               // yes, I really do not want to bind input values...
+               if (!$stmt = mysqli_prepare($link, 'CALL p(?, @version)'))
+                       printf("[038] Cannot prepare CALL, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               $version = 'myversion';
+               if (!mysqli_stmt_bind_param($stmt, 's', $version))
+                       printf("[039] Cannot bind input parameter, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[040] Cannot execute CALL, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!mysqli_stmt_close($stmt))
+                       printf("[041] Cannot close statement, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if (!$stmt = mysqli_prepare($link, 'SELECT @version AS _version'))
+                       printf("[042] Cannot prepare SELECT, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+               if (!mysqli_stmt_execute($stmt))
+                       printf("[043] Cannot execute SELECT, [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               $version = 'unknown';
+               if (!mysqli_stmt_bind_result($stmt, $version) ||
+                               !mysqli_stmt_fetch($stmt))
+                       printf("[044] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               if ($version !== "myversion")
+                       printf("[045] Results seem wrong, got %s, [%d] %s\n",
+                               $version,
+                               mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+               mysqli_stmt_free_result($stmt);
+               mysqli_stmt_close($stmt);
+
+       } else {
+               printf("[046] Cannot create SP, [%d] %s.\n", mysqli_errno($link), mysqli_error($link));
+       }
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
index 8f01f28c4db244cc39775027ee40b71eb8ba7468..12489cef5dcb746c1a49a5d9343a1a9c112721cb 100644 (file)
@@ -102,7 +102,7 @@ object(stdClass)#%d (11) {
   ["max_length"]=>
   int(0)
   ["length"]=>
-  int(17)
+  int(%d)
   ["charsetnr"]=>
   int(63)
   ["flags"]=>
@@ -200,7 +200,7 @@ object(stdClass)#%d (11) {
   [u"max_length"]=>
   int(0)
   [u"length"]=>
-  int(17)
+  int(%d)
   [u"charsetnr"]=>
   int(63)
   [u"flags"]=>
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt
new file mode 100644 (file)
index 0000000..12e33f2
--- /dev/null
@@ -0,0 +1,94 @@
+--TEST--
+mysqli_stmt_get_result() - SHOW, DESCRIBE, EXPLAIN
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_stmt_get_result'))
+       die('skip mysqli_stmt_get_result not available');
+?>
+--FILE--
+<?php
+       /*
+       NOTE: no datatype tests here! This is done by
+       mysqli_stmt_bind_result.phpt already. Restrict
+       this test case to the basics.
+       */
+       include "connect.inc";
+       require('table.inc');
+
+       if (!$stmt = mysqli_stmt_init($link))
+               printf("[001] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+       if (mysqli_query($link, 'PREPARE mystmt FROM "SHOW ENGINES"')) {
+               mysqli_query($link, 'DEALLOCATE PREPARE mystmt');
+
+               if (!$stmt->prepare('SHOW ENGINES') ||
+                       !$stmt->execute())
+                       printf("[002] [%d] %s\n", $stmt->errno, $stmt->error);
+
+               if (!$res = $stmt->get_result())
+                       printf("[003] [%d] %s\n", $stmt->errno, $stmt->error);
+
+               $engines = mysqli_fetch_all($res, MYSQLI_NUM);
+               if      (empty($engines)) {
+                       printf("[004] It is very unlikely that SHOW ENGINES returns no data, check manually\n");
+               } else {
+                       $found = false;
+                       foreach ($engines as $k => $engine)
+                               foreach ($engine as $k => $v)
+                                       if (stristr('MyISAM', $v)) {
+                                               $found = true;
+                                               break;
+                                       }
+                       if (!$found)
+                               printf("[005] It is very unlikely that SHOW ENGINES does not show MyISAM, check manually\n");
+               }
+               mysqli_free_result($res);
+       }
+
+       if (mysqli_query($link, 'PREPARE mystmt FROM "DESCRIBE test id"')) {
+               mysqli_query($link, 'DEALLOCATE PREPARE mystmt');
+
+               if (!$stmt->prepare('DESCRIBE test id') ||
+                       !$stmt->execute())
+                       printf("[006] [%d] %s\n", $stmt->errno, $stmt->error);
+
+               if (!$res = $stmt->get_result())
+                       printf("[007] [%d] %s\n", $stmt->errno, $stmt->error);
+
+               $description = mysqli_fetch_assoc($res);
+               if ($description['Field'] != 'id') {
+                       printf("[008] Returned data seems wrong, [%d] %s\n",
+                               mysqli_errno($link), mysqli_error($link));
+                       var_dump($description);
+               }
+               mysqli_free_result($res);
+       }
+
+       if (mysqli_query($link, 'PREPARE mystmt FROM "EXPLAIN SELECT id FROM test"')) {
+               mysqli_query($link, 'DEALLOCATE PREPARE mystmt');
+
+               if (!$stmt->prepare('EXPLAIN SELECT id FROM test') ||
+                       !$stmt->execute())
+                       printf("[009] [%d] %s\n", $stmt->errno, $stmt->error);
+
+               if (!$res = $stmt->get_result())
+                       printf("[010] [%d] %s\n", $stmt->errno, $stmt->error);
+
+               $tmp = mysqli_fetch_assoc($res);
+               if (empty($tmp))
+                       printf("[011] Empty EXPLAIN result set seems wrong, check manually, [%d] %s\n",
+                               mysqli_errno($link), mysqli_error($link));
+               mysqli_free_result($res);
+       }
+       mysqli_close($link);
+
+       print "done!";
+?>
+--EXPECTF--
+done!
+--UEXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_types.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_types.phpt
new file mode 100644 (file)
index 0000000..f70eea7
--- /dev/null
@@ -0,0 +1,255 @@
+--TEST--
+mysqli_stmt_get_result - data types
+--SKIPIF--
+<?php
+       require_once('skipif.inc');
+       require_once('skipifemb.inc');
+       require_once('skipifconnectfailure.inc');
+
+       if (!function_exists('mysqli_stmt_get_result'))
+               die("skip mysqli_stmt_get_result() not available");
+?>
+--FILE--
+<?php
+       require('connect.inc');
+       if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+               printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+       $hint_str_or_unicode = ini_get('unicode.semantics') ? 'unicode' : 'string';
+
+       function func_mysqli_stmt_get_result($link, $engine, $bind_type, $sql_type, $bind_value, $offset, $type_hint = null) {
+
+               if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+                       printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+                       // don't bail - column type might not be supported by the server, ignore this
+                       return false;
+               }
+
+               if (!$stmt = mysqli_stmt_init($link)) {
+                       printf("[%04d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+                       return false;
+               }
+
+               if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) {
+                       printf("[%04d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       return false;
+               }
+
+               $id = null;
+               if (!mysqli_stmt_bind_param($stmt, "i" . $bind_type, $id, $bind_value)) {
+                       printf("[%04d] [%d] %s\n", $offset + 3, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       mysqli_stmt_close($stmt);
+                       return false;
+               }
+
+               for ($id = 1; $id < 4; $id++) {
+                       if (!mysqli_stmt_execute($stmt)) {
+                               printf("[%04d] [%d] %s\n", $offset + 3 + $id, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                               mysqli_stmt_close($stmt);
+                               return false;
+                       }
+               }
+               mysqli_stmt_close($stmt);
+
+               $stmt = mysqli_stmt_init($link);
+
+               if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) {
+                       printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       mysqli_stmt_close($stmt);
+                       return false;
+               }
+
+               if (!mysqli_stmt_execute($stmt)) {
+                       printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       mysqli_stmt_close($stmt);
+                       return false;
+               }
+
+               $result = mysqli_stmt_result_metadata($stmt);
+
+               if (!$res = mysqli_stmt_get_result($stmt)) {
+                       printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+                       mysqli_stmt_close($stmt);
+                       return false;
+               }
+               $num = 0;
+               $fields = mysqli_fetch_fields($result);
+
+               while ($row = mysqli_fetch_assoc($res)) {
+                       $bind_res = &$row['label'];
+                       if (!gettype($bind_res) == 'unicode') {
+                               if ($bind_res !== $bind_value && (!$type_hint || ($type_hint !== gettype($bind_res)))) {
+                                       printf("[%04d] [%d] Expecting %s/'%s' [type hint = %s], got %s/'%s'\n",
+                                               $offset + 10, $num,
+                                               gettype($bind_value), $bind_value, $type_hint,
+                                               gettype($bind_res), $bind_res);
+                                               mysqli_free_result($res);
+                                               mysqli_stmt_close($stmt);
+                                               return false;
+                               }
+                       }
+                       $num++;
+               }
+
+               if ($num != 3) {
+                       printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n",
+                               $offset + 11, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num);
+                       mysqli_free_result($res);
+                       mysqli_stmt_close($stmt);
+                       return false;
+               }
+
+               mysqli_free_result($res);
+               mysqli_stmt_close($stmt);
+               return true;
+       }
+
+
+       function func_mysqli_stmt_bind_make_string($len) {
+
+               $ret = '';
+               for ($i = 0; $i < $len; $i++)
+                       $ret .= chr(mt_rand(65, 90));
+
+               return $ret;
+       }
+
+       func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT", -11, 20);
+       func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT", NULL, 40);
+       func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT UNSIGNED", 1, 60);
+       func_mysqli_stmt_get_result($link, $engine, "i", "TINYINT UNSIGNED", NULL, 80);
+
+       func_mysqli_stmt_get_result($link, $engine, "i", "BOOL", 1, 100);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BOOL", NULL, 120);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BOOLEAN", 0, 140);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BOOLEAN", NULL, 160);
+
+       func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT", -32768, 180);
+       func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT", 32767, 200);
+       func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT", NULL, 220);
+       func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 240);
+       func_mysqli_stmt_get_result($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 260);
+
+       func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT", -8388608, 280, "integer");
+       func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT", 8388607, 300, "integer");
+       func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT", NULL, 320);
+       func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT UNSIGNED", 16777215, 340, "integer");
+       func_mysqli_stmt_get_result($link, $engine, "d", "MEDIUMINT UNSIGNED", NULL, 360);
+
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? max(-1 * PHP_INT_MAX + 1, -2147483648) : 1, 380);
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", -2147483647, 400, "integer");
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? min(2147483647, PHP_INT_MAX) : 1, 420);
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER", NULL, 440);
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, 2147483647) : 1, 460);
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER UNSIGNED", 4294967295, 480, (defined("PHP_INT_MAX") && (4294967295 > PHP_INT_MAX)) ? "string" : null);
+       func_mysqli_stmt_get_result($link, $engine, "i", "INTEGER UNSIGNED", NULL, 500);
+
+       /* test is broken too: we bind "integer" but value is a float
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", -9223372036854775808, 520);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", 18446744073709551615, 560);
+       */
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", NULL, 540);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", NULL, 580);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", -1, 1780);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", 1, 1800);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 1820);
+       func_mysqli_stmt_get_result($link, $engine, "i", "BIGINT UNSIGNED", PHP_INT_MAX, 1840);
+       func_mysqli_stmt_get_result($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 1860);
+       func_mysqli_stmt_get_result($link, $engine, "s", "BIGINT", "-9223372036854775808", 1880);
+
+       func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 600);
+       func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT", NULL, 620);
+       func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 640);
+       func_mysqli_stmt_get_result($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 660);
+
+       // Yes, we need the temporary variable. The PHP casting will fouls us otherwise.
+       $tmp = strval('-99999999.99');
+       func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2)", $tmp, 680, "string");
+       func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2)", NULL, 700);
+       $tmp = strval('99999999.99');
+       func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", $tmp , 720, "string");
+       func_mysqli_stmt_get_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 740);
+       $tmp = strval('-99999999.99');
+       func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 760, "string");
+       func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 780);
+       $tmp = strval('99999999.99');
+       func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 800, "string");
+       func_mysqli_stmt_get_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 820);
+
+       // don't care about date() strict TZ warnings...
+       func_mysqli_stmt_get_result($link, $engine, "s", "DATE", @date('Y-m-d'), 840);
+       func_mysqli_stmt_get_result($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 860);
+       func_mysqli_stmt_get_result($link, $engine, "s", "DATE", NULL, 880);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 900);
+       func_mysqli_stmt_get_result($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 920);
+       func_mysqli_stmt_get_result($link, $engine, "s", "DATETIME", NULL, 940);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 960);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "TIME", @date('H:i:s'), 980);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 1000);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TIME", NULL, 1020);
+
+       $tmp = intval(@date('Y'));
+       func_mysqli_stmt_get_result($link, $engine, "s", "YEAR", $tmp, 1040, "integer");
+       func_mysqli_stmt_get_result($link, $engine, "s", "YEAR NOT NULL", $tmp, 1060, "integer");
+       func_mysqli_stmt_get_result($link, $engine, "s", "YEAR", NULL, 1080);
+
+       $string255 = func_mysqli_stmt_bind_make_string(255);
+       func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(1)", "a", 1110, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(255)", $string255, 1120, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(1) NOT NULL", "a", 1140, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "CHAR(1)", NULL, 1160);
+
+       $string65k = func_mysqli_stmt_bind_make_string(65535);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(1)", "a", 1180, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(255)", $string255, 1200, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(65635)", $string65k, 1220, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 1240, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARCHAR(1)", NULL, 1260);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1)", "a", 1280);
+       func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1)", chr(0), 1300);
+       func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1) NOT NULL", "b", 1320);
+       func_mysqli_stmt_get_result($link, $engine, "s", "BINARY(1)", NULL, 1340);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1)", "a", 1360);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1)", chr(0), 1380);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 1400);
+       func_mysqli_stmt_get_result($link, $engine, "s", "VARBINARY(1)", NULL, 1420);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB", "a", 1440);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB", chr(0), 1460);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB NOT NULL", "b", 1480);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYBLOB", NULL, 1500);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYTEXT", "a", 1520, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYTEXT NOT NULL", "a", 1540, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "TINYTEXT", NULL, 1560, $hint_str_or_unicode);
+
+       // Note: you cannot insert any blob values this way. But you can check the API at least partly this way
+       // Extra BLOB tests are in mysqli_stmt_send_long()
+       func_mysqli_stmt_get_result($link, $engine, "b", "BLOB", b"", 1580);
+       func_mysqli_stmt_get_result($link, $engine, "b", "TEXT", "", 1600, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "b", "MEDIUMBLOB", b"", 1620);
+       func_mysqli_stmt_get_result($link, $engine, "b", "MEDIUMTEXT", "", 1640, $hint_str_or_unicode);
+
+       /* Is this one related? http://bugs.php.net/bug.php?id=35759 */
+       func_mysqli_stmt_get_result($link, $engine, "b", "LONGBLOB", "", 1660);
+       func_mysqli_stmt_get_result($link, $engine, "b", "LONGTEXT", "", 1680, $hint_str_or_unicode);
+
+       func_mysqli_stmt_get_result($link, $engine, "s", "ENUM('a', 'b')", "a", 1700, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "ENUM('a', 'b')", NULL, 1720, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "SET('a', 'b')", "a", 1740, $hint_str_or_unicode);
+       func_mysqli_stmt_get_result($link, $engine, "s", "SET('a', 'b')", NULL, 1760, $hint_str_or_unicode);
+
+       mysqli_close($link);
+       print "done!";
+?>
+--EXPECTF--
+done!
\ No newline at end of file
diff --git a/ext/mysqli/tests/skipifunicode.inc b/ext/mysqli/tests/skipifunicode.inc
new file mode 100644 (file)
index 0000000..23cd79d
--- /dev/null
@@ -0,0 +1,5 @@
+<?php
+if (ini_get("unicode.semantics")){
+       die('skip Test doesn't work in Unicode mode');
+}
+?>