summaryrefslogtreecommitdiff
path: root/ext/mysqli
diff options
context:
space:
mode:
authorUlf Wendel <uw@php.net>2007-10-10 10:18:50 +0000
committerUlf Wendel <uw@php.net>2007-10-10 10:18:50 +0000
commit3a3594d3f1298b04e1cd9c8988a5a195a21a32c5 (patch)
treea8860c4171fcbeeed6650866d17a3559107f7d05 /ext/mysqli
parent5ec98ed1c8b9b9a55dd3c401dace378c0d045077 (diff)
downloadphp-git-3a3594d3f1298b04e1cd9c8988a5a195a21a32c5.tar.gz
Adding new tests: mysqli_s*.phpt
Diffstat (limited to 'ext/mysqli')
-rw-r--r--ext/mysqli/tests/mysqli_select_db.phpt74
-rwxr-xr-xext/mysqli/tests/mysqli_send_query.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_set_charset.phpt128
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_default.phpt120
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler.phpt232
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt85
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt63
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt65
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt74
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt65
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt61
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt110
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt74
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt73
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt110
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt81
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt104
-rw-r--r--ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt67
-rw-r--r--ext/mysqli/tests/mysqli_set_opt.phpt69
-rw-r--r--ext/mysqli/tests/mysqli_set_opt_numeric_and_datetime_as_unicode.phpt148
-rwxr-xr-xext/mysqli/tests/mysqli_slave_query.phpt50
-rw-r--r--ext/mysqli/tests/mysqli_sqlstate.phpt46
-rw-r--r--ext/mysqli/tests/mysqli_ssl_set.phpt61
-rw-r--r--ext/mysqli/tests/mysqli_stat.phpt40
-rw-r--r--ext/mysqli/tests/mysqli_stmt_affected_rows.phpt183
-rw-r--r--ext/mysqli/tests/mysqli_stmt_attr_get.phpt66
-rw-r--r--ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt26
-rw-r--r--ext/mysqli/tests/mysqli_stmt_attr_set.phpt263
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param.phpt398
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt203
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt126
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result.phpt330
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt157
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt333
-rw-r--r--ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt378
-rw-r--r--ext/mysqli/tests/mysqli_stmt_close.phpt87
-rw-r--r--ext/mysqli/tests/mysqli_stmt_data_seek.phpt95
-rw-r--r--ext/mysqli/tests/mysqli_stmt_errno.phpt64
-rw-r--r--ext/mysqli/tests/mysqli_stmt_error.phpt64
-rw-r--r--ext/mysqli/tests/mysqli_stmt_execute.phpt81
-rw-r--r--ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt185
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch.phpt94
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt71
-rw-r--r--ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt52
-rw-r--r--ext/mysqli/tests/mysqli_stmt_field_count.phpt94
-rw-r--r--ext/mysqli/tests/mysqli_stmt_free_result.phpt82
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result.phpt209
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result2.phpt191
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt129
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt47
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt260
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt237
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt94
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt126
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_result_types.phpt255
-rw-r--r--ext/mysqli/tests/mysqli_stmt_get_warnings.phpt87
-rw-r--r--ext/mysqli/tests/mysqli_stmt_init.phpt54
-rw-r--r--ext/mysqli/tests/mysqli_stmt_insert_id.phpt73
-rw-r--r--ext/mysqli/tests/mysqli_stmt_num_rows.phpt104
-rw-r--r--ext/mysqli/tests/mysqli_stmt_param_count.phpt68
-rw-r--r--ext/mysqli/tests/mysqli_stmt_prepare.phpt52
-rw-r--r--ext/mysqli/tests/mysqli_stmt_reset.phpt108
-rw-r--r--ext/mysqli/tests/mysqli_stmt_result_metadata.phpt157
-rw-r--r--ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt229
-rw-r--r--ext/mysqli/tests/mysqli_stmt_send_long_data.phpt129
-rw-r--r--ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt95
-rw-r--r--ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt100
-rw-r--r--ext/mysqli/tests/mysqli_stmt_sqlstate.phpt59
-rw-r--r--ext/mysqli/tests/mysqli_stmt_store_result.phpt86
-rw-r--r--ext/mysqli/tests/mysqli_stmt_unclonable.phpt25
-rw-r--r--ext/mysqli/tests/mysqli_store_result.phpt60
71 files changed, 8516 insertions, 0 deletions
diff --git a/ext/mysqli/tests/mysqli_select_db.phpt b/ext/mysqli/tests/mysqli_select_db.phpt
new file mode 100644
index 0000000000..c121d66504
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_select_db.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli_select_db()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_select_db()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_select_db($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!is_null($tmp = @mysqli_select_db($link, $db, "foo")))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* does not make too much sense, unless we have access to at least one more database than $db */
+ if (!mysqli_select_db($link, $db))
+ printf("[005] Cannot select DB %s, [%d] %s\n", $db, mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT DATABASE() AS dbname"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['dbname'] !== (string)$db)
+ printf("[008] Expecting database '%s', found '%s'\n", $db, $row['dbname']);
+ mysqli_free_result($res);
+
+ if (mysqli_select_db($link, 'mysql')) {
+ // Yippie, a second database to play with - that's great because mysqli_select_db
+ // ($db) was done by mysqli__connect() already and the previous test
+ // was quite useless
+ if (!$res = mysqli_query($link, "SELECT DATABASE() AS dbname"))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (strtolower($row['dbname']) !== 'mysql')
+ printf("[011] Expecting database 'mysql', found '%s'\n", $row['dbname']);
+ mysqli_free_result($res);
+ }
+
+ mysqli_report(MYSQLI_REPORT_OFF);
+ mysqli_select_db($link, 'I can not imagine that this database exists');
+ mysqli_report(MYSQLI_REPORT_ERROR);
+ mysqli_select_db($link, 'I can not imagine that this database exists');
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_select_db($link, $db)))
+ printf("[012] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!\n";
+?>
+--EXPECTF--
+Warning: mysqli_select_db(): (%d/%d): Unknown database '%s' in %s on line %d
+
+Warning: mysqli_select_db(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_send_query.phpt b/ext/mysqli/tests/mysqli_send_query.phpt
new file mode 100755
index 0000000000..ccddfd2339
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_send_query.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_send_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_send_query')) {
+ die("skip mysqli_send_query() not available");
+}
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+?>
+--FILE--
+<?php
+ /* NOTE: tests is a stub, but function is deprecated, as long as it does not crash when invoking it... */
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_send_query()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_send_query($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ $query = array();
+ if (NULL !== ($tmp = @mysqli_send_query($link, $query)))
+ printf("[004] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($tmp = mysqli_send_query($link, 'SELECT 1')))
+ printf("[005] Expecting integer/any value, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_send_query($link, 'SELECT 1')))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_send_query(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_charset.phpt b/ext/mysqli/tests/mysqli_set_charset.phpt
new file mode 100644
index 0000000000..5e6584bba8
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_charset.phpt
@@ -0,0 +1,128 @@
+--TEST--
+mysqli_set_charset()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('mysqli_set_charset'))
+ die("skip Function not available");
+if (ini_get("unicode.semantics"))
+ die("skip: mysqli_set_charset() is disabled in unicode");
+
+require_once('connect.inc');
+if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ die(sprintf("skip Cannot connect, [%d] %s", mysqli_connect_errno(), mysqli_connect_error()));
+
+if (!($res = mysqli_query($link, 'SELECT version() AS server_version')) ||
+ !($tmp = mysqli_fetch_assoc($res))) {
+ mysqli_close($link);
+ die(sprintf("skip Cannot check server version, [%d] %s\n",
+ mysqli_errno($link), mysqli_error($link)));
+}
+mysqli_free_result($res);
+$version = explode('.', $tmp['server_version']);
+if (empty($version)) {
+ mysqli_close($link);
+ die(sprintf("skip Cannot check server version, based on '%s'",
+ $tmp['server_version']));
+}
+
+if ($version[0] <= 4 && $version[1] < 1) {
+ mysqli_close($link);
+ die(sprintf("skip Requires MySQL Server 4.1+\n"));
+}
+
+if ((($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin1"', MYSQLI_STORE_RESULT)) &&
+ (mysqli_num_rows($res) == 1)) ||
+ (($res = mysqli_query($link, 'SHOW CHARACTER SET LIKE "latin2"', MYSQLI_STORE_RESULT)) &&
+ (mysqli_num_rows($res) == 1))
+ ) {
+ // ok, required latin1 or latin2 are available
+ mysqli_close($link);
+} else {
+ die(sprintf("skip Requires character set latin1 or latin2\n"));
+ mysqli_close($link);
+}
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_set_charset()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_charset($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_charset($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if (!$character_set_connection = $tmp['charset'])
+ printf("[008] Cannot determine current character set and collation\n");
+
+ $new_charset = ('latin1' == $character_set_connection) ? 'latin2' : 'latin1';
+ if (!$res = mysqli_query($link, sprintf('SHOW CHARACTER SET LIKE "%s"', $new_charset), MYSQLI_STORE_RESULT))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (mysqli_num_rows($res) == 0)
+ printf("[010] Test will fail, because alternative test character set '%s' seems not supported\n", $new_charset);
+
+ if (false !== ($ret = mysqli_set_charset($link, "this is not a valid character set")))
+ printf("[011] Expecting boolean/false because of invalid character set, got %s/%s\n", gettype($ret), $ret);
+
+ mysqli_close($link);
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[012] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (true !== ($ret = mysqli_set_charset($link, $new_charset)))
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($ret), $ret);
+
+ if (!$res = mysqli_query($link, 'SELECT @@character_set_connection AS charset, @@collation_connection AS collation'))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $tmp = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ if ($new_charset !== $tmp['charset'])
+ printf("[015] Character set not changed? Expecting %s, got %s\n", $new_charset, $tmp['charset']);
+
+ if (!$res = mysqli_query($link, "SHOW CHARACTER SET"))
+ printf("[016] Cannot get list of character sets\n");
+
+ while ($tmp = mysqli_fetch_assoc($res)) {
+ if ('ucs2' == $tmp['Charset'])
+ continue;
+
+ /* Uncomment to see where it hangs - var_dump($tmp); flush(); */
+ if (!@mysqli_set_charset($link, $tmp['Charset'])) {
+ printf("[017] Cannot set character set to '%s', [%d] %s\n", $tmp['Charset'],
+ mysqli_errno($link), mysqli_error($link));
+ continue;
+ }
+
+ /* Uncomment to see where it hangs - var_dump($tmp); flush(); */
+ if (!mysqli_query($link, sprintf("SET NAMES %s", mysqli_real_escape_string($link, $tmp['Charset']))))
+ printf("[018] Cannot run SET NAMES %s, [%d] %s\n", $tmp['Charset'], mysqli_errno($link), mysqli_error($link));
+ }
+ mysqli_free_result($res);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_set_charset($link, $new_charset)))
+ printf("[016] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_set_charset(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_default.phpt b/ext/mysqli/tests/mysqli_set_local_infile_default.phpt
new file mode 100644
index 0000000000..167fc0f80d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_default.phpt
@@ -0,0 +1,120 @@
+--TEST--
+mysqli_set_local_infile_default()
+--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');
+?>
+--INI--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+
+ $link = $tmp = null;
+ if (!is_null($tmp = @mysqli_set_local_infile_default()))
+ printf("[001] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link)))
+ printf("[002] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ $link = new mysqli();
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link)))
+ printf("[002a] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ include("table.inc");
+
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link, 'foo')))
+ printf("[003] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+
+ 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(4);
+ $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);
+
+ $expected = array(
+ array('id' => 97, 'label' => 'x'),
+ array('id' => 98, 'label' => 'y'),
+ array('id' => 99, 'label' => 'z'),
+ );
+ try_handler(20, $link, $file, 'default', $expected);
+
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(30, $link, $file, 'callback_simple', $expected);
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = @mysqli_set_local_infile_default($link)))
+ printf("[300] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_simple'
+Callback: 0
+Callback: 1
+Callback set to 'default'
+Callback set to 'callback_simple'
+Callback: 2
+Callback: 3
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler.phpt
new file mode 100644
index 0000000000..751d4b9643
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler.phpt
@@ -0,0 +1,232 @@
+--TEST--
+mysqli_set_local_infile_handler()
+--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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ 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);
+ }
+
+ function callback_fclose($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+
+ fclose($fp);
+ return strlen($buffer);
+ }
+
+ function callback_closefile($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_resource($fp))
+ fclose($fp);
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ function callback_invalid_args($fp, &$buffer, $buflen) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ $buffer = fread($fp, $buflen);
+
+ return strlen($buffer);
+ }
+
+ function callback_error($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ $buffer = fread($fp, $buflen);
+ $error = 'How to access this error?';
+
+ return -1;
+ }
+
+ if (!is_null($tmp = @mysqli_set_local_infile_handler()))
+ printf("[001] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ $handle = null;
+ if (!is_null($tmp = @mysqli_set_local_infile_handler($handle)))
+ printf("[002] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ $handle = @new mysqli();
+ if (!is_null($tmp = @mysqli_set_local_infile_handler($handle, 'callback_simple')))
+ printf("[003] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ if (false !== ($tmp = @mysqli_set_local_infile_handler($link, 'unknown')))
+ printf("[004] Expecting false/boolean got %s/%s\n", $tmp, gettype($tmp));
+
+ $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);
+
+ $expected = array();
+ try_handler(20, $link, $file, 'callback_fclose', $expected);
+
+ // FIXME - TODO - KLUDGE -
+ // IMHO this is wrong. ext/mysqli should bail as the function signature
+ // is not complete. That's a BC break, OK, but it makes perfectly sense.
+ $expected = array();
+ try_handler(30, $link, $file, 'callback_invalid_args', $expected);
+
+ $expected = array();
+ try_handler(40, $link, $file, 'callback_error', $expected);
+
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = @mysqli_set_local_infile_handler($link, 'callback_simple')))
+ printf("[300] Expecting NULL/NULL got %s/%s\n", $tmp, gettype($tmp));
+
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_simple'
+Callback: 0
+Callback: 1
+Callback set to 'callback_fclose'
+Callback: 0
+[022] LOAD DATA failed, [2000] File handle closed in handler
+Callback set to 'callback_invalid_args'
+Callback: 0
+Callback: 1
+[037] More results than expected!
+array(2) {
+ ["id"]=>
+ string(2) "97"
+ ["label"]=>
+ string(1) "x"
+}
+array(2) {
+ ["id"]=>
+ string(2) "98"
+ ["label"]=>
+ string(1) "y"
+}
+array(2) {
+ ["id"]=>
+ string(2) "99"
+ ["label"]=>
+ string(1) "z"
+}
+Callback set to 'callback_error'
+Callback: 0
+[042] LOAD DATA failed, [2000] How to access this error?
+done!
+--UEXPECTF--
+Callback set to 'callback_simple'
+Callback: 0
+Callback: 1
+Callback set to 'callback_fclose'
+Callback: 0
+[022] LOAD DATA failed, [2000] File handle closed in handler
+Callback set to 'callback_invalid_args'
+Callback: 0
+Callback: 1
+[037] More results than expected!
+array(2) {
+ [u"id"]=>
+ unicode(2) "97"
+ [u"label"]=>
+ unicode(1) "x"
+}
+array(2) {
+ [u"id"]=>
+ unicode(2) "98"
+ [u"label"]=>
+ unicode(1) "y"
+}
+array(2) {
+ [u"id"]=>
+ unicode(2) "99"
+ [u"label"]=>
+ unicode(1) "z"
+}
+Callback set to 'callback_error'
+Callback: 0
+[042] LOAD DATA failed, [2000] How to access this error?
+done!
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt
new file mode 100644
index 0000000000..2ea5ceb0c3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_bad_character.phpt
@@ -0,0 +1,85 @@
+--TEST--
+mysqli_set_local_infile_handler() - random ASCII character including \0
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+require_once('connect.inc');
+
+if (!function_exists('mysqli_set_local_infile_handler'))
+ die("skip - function not available.");
+
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_bad_character($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+
+ $num_chars = (ini_get('unicode.semantics')) ? (floor($buflen / 2) - 10) : ($buflen - 5);
+ $part1 = floor($num_chars / 2);
+ $part2 = $num_chars - $part1;
+
+ $buffer = '';
+ for ($i = 0; $i < $part1; $i++)
+ $buffer .= chr(mt_rand(0, 255));
+
+ $buffer .= ';"';
+
+ for ($i = 0; $i < $part2; $i++)
+ $buffer .= chr(mt_rand(0, 255));
+
+ $buffer .= '";';
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(5);
+ /* we feed the handler with random data, therefore we cannot specify and expected rows */
+ try_handler(20, $link, $file, 'callback_bad_character');
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_bad_character'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt
new file mode 100644
index 0000000000..6c557201bd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_buffer_overflow.phpt
@@ -0,0 +1,63 @@
+--TEST--
+mysqli_set_local_infile_handler() - buffer overflow
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_buffer_overflow($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+ $buffer = fread($fp, $buflen);
+
+ $buffer = str_repeat(';', $buflen * 2);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(5);
+ $expected = array();
+ try_handler(20, $link, $file, 'callback_buffer_overflow', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_buffer_overflow'
+Callback: 0
+
+Warning: mysqli_query(): Too much data returned in %s on line %d
+[022] LOAD DATA failed, [%d] Too much data returned
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt
new file mode 100644
index 0000000000..d9335813be
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_close_link.phpt
@@ -0,0 +1,65 @@
+--TEST--
+mysqli_set_local_infile_handler() - close database link
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ include "connect.inc";
+ include("table.inc");
+ require_once('local_infile_tools.inc');
+
+ function callback_close_link($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_object($link))
+ mysqli_close($link);
+
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_close_link', $expected);
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_close_link'
+Callback: 0
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt
new file mode 100644
index 0000000000..4bdb54b1cb
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_closefile.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli_set_local_infile_handler() - do not use the file pointer
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ include "connect.inc";
+ include("table.inc");
+ require_once('local_infile_tools.inc');
+
+ function callback_closefile($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_resource($fp))
+ fclose($fp);
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_closefile', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_closefile'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt
new file mode 100644
index 0000000000..efb72d2859
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_kill_link.phpt
@@ -0,0 +1,65 @@
+--TEST--
+mysqli_set_local_infile_handler() - kill database link
+--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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ include "connect.inc";
+ include("table.inc");
+ require_once('local_infile_tools.inc');
+
+ function callback_kill_link($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_object($link))
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ mysqli_set_local_infile_default($link);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_kill_link', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_kill_link'
+Callback: 0
+[022] LOAD DATA failed, [2000] Can't execute load data local init callback function
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt
new file mode 100644
index 0000000000..3b8813aeb7
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_negative_len.phpt
@@ -0,0 +1,61 @@
+--TEST--
+mysqli_set_local_infile_handler() - negative return value/buflen to indicate an error
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_negative_len($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation);
+ $buffer = fread($fp, $buflen);
+
+ $error = "negative length means error";
+ return -1;
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array();
+ try_handler(20, $link, $file, 'callback_negative_len', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_negative_len'
+Callback: 0
+[022] LOAD DATA failed, [2000] negative length means error
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt
new file mode 100644
index 0000000000..50be4a5937
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_nested_call.phpt
@@ -0,0 +1,110 @@
+--TEST--
+mysqli_set_local_infile_handler() - nested calls
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ 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 - callback_simple(): %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";
+ }
+
+ /* report the wrong length */
+ return strlen($buffer);
+ }
+
+ function callback_report_short_len($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback - report_short_len(): %d\n", $invocation++);
+ return callback_simple($fp, $buffer, $buflen, $error);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(20, $link, $file, 'callback_report_short_len', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_report_short_len'
+Callback - report_short_len(): 0
+Callback - callback_simple(): 0
+Callback - report_short_len(): 1
+Callback - callback_simple(): 1
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt
new file mode 100644
index 0000000000..2858e40346
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_new_query.phpt
@@ -0,0 +1,74 @@
+--TEST--
+mysqli_set_local_infile_handler() - run new query on db link
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_new_query($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_object($link)) {
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[Callback 001 - %03d] Cannot run query, [%d] %s\n",
+ $invocation, mysqli_errno($link), mysqli_error($link));
+ }
+ if ($res)
+ mysqli_free_result($res);
+ }
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ mysqli_set_local_infile_default($link);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_new_query', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_new_query'
+Callback: 0
+[Callback 001 - 001] Cannot run query, [2014] Commands out of sync; you can't run this command now
+[022] LOAD DATA failed, [2000] Can't execute load data local init callback function
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt
new file mode 100644
index 0000000000..c92f93762b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_nofileop.phpt
@@ -0,0 +1,73 @@
+--TEST--
+mysqli_set_local_infile_handler() - do not use the file pointer
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_nofileop($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_nofileop', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_nofileop'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
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
index 0000000000..a4f20cb75e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_openbasedir.phpt
@@ -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_set_local_infile_handler_replace_buffer.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt
new file mode 100644
index 0000000000..d0115e1c3f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_replace_buffer.phpt
@@ -0,0 +1,81 @@
+--TEST--
+mysqli_set_local_infile_handler() - replace buffer pointer
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_replace_buffer($fp, &$buffer, $buflen, &$error) {
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+
+ $buffer = fread($fp, $buflen);
+
+ $ret = "1;'a';\n";
+ $buffer = $ret;
+
+ $num_chars = (ini_get('unicode.semantics')) ? floor($buflen / 2) : $buflen;
+ assert(strlen($buffer) < $num_chars);
+
+ if ($invocation > 10)
+ return 0;
+
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ if (!try_handler(20, $link, $file, 'callback_replace_buffer', $expected))
+ printf("[008] Failure\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_replace_buffer'
+Callback: 0
+Callback: 1
+Callback: 2
+Callback: 3
+Callback: 4
+Callback: 5
+Callback: 6
+Callback: 7
+Callback: 8
+Callback: 9
+Callback: 10
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt
new file mode 100644
index 0000000000..78f2fced19
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_short_len.phpt
@@ -0,0 +1,104 @@
+--TEST--
+mysqli_set_local_infile_handler() - report shorter buffer
+--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 (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+
+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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_short_len($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";
+ }
+
+ /* report the wrong length */
+ return strlen($buffer) - 1;
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(
+ array('id' => 98, 'label' => 'x'),
+ array('id' => 99, 'label' => 'y'),
+ array('id' => 100, 'label' => 'z'),
+ );
+ try_handler(20, $link, $file, 'callback_short_len', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_short_len'
+Callback: 0
+
+Warning: mysqli_query(): Mismatch between the return value of the callback and the content length of the buffer. in %s on line %d
+[022] LOAD DATA failed, [2000] Mismatch between the return value of the callback and the content length of the buffer.
+[024/0] [0] ''
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt b/ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt
new file mode 100644
index 0000000000..4a321bf30e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_local_infile_handler_unregister.phpt
@@ -0,0 +1,67 @@
+--TEST--
+mysqli_set_local_infile_handler() - do not use the file pointer
+--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--
+mysqli.allow_local_infile=1
+--FILE--
+<?php
+ require_once('connect.inc');
+ require_once('local_infile_tools.inc');
+ require_once('table.inc');
+
+ function callback_unregister($fp, &$buffer, $buflen, &$error) {
+ global $link;
+ static $invocation = 0;
+
+ printf("Callback: %d\n", $invocation++);
+ flush();
+ if (is_resource($fp))
+ fclose($fp);
+ $buffer = "1;'a';\n";
+ if ($invocation > 10)
+ return 0;
+
+ mysqli_set_local_infile_default($link);
+ return strlen($buffer);
+ }
+
+ $file = create_standard_csv(1);
+ $expected = array(array('id' => 1, 'label' => 'a'));
+ try_handler(20, $link, $file, 'callback_unregister', $expected);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Callback set to 'callback_unregister'
+Callback: 0
+
+Warning: mysqli_query(): File handle closed in %s on line %d
+[022] LOAD DATA failed, [2000] File handle closed
+[024/0] [0] ''
+done!
diff --git a/ext/mysqli/tests/mysqli_set_opt.phpt b/ext/mysqli/tests/mysqli_set_opt.phpt
new file mode 100644
index 0000000000..d5c41827c3
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_opt.phpt
@@ -0,0 +1,69 @@
+--TEST--
+mysqli_set_opt()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_set_opt()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_opt($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $link = mysqli_init();
+
+ if (!is_null($tmp = @mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_opt($link, "s", 'extra_my.cnf')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0', 'foo')))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ // print "run_tests.php don't fool me with your 'ungreedy' expression '.+?'!\n";
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_GROUP, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_LOCAL_INFILE, 1));
+ var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0'));
+ var_dump(mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket));
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_GROUP, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf'));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10));
+ var_dump(mysqli_set_opt($link, MYSQLI_OPT_LOCAL_INFILE, 1));
+ var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=0'));
+ var_dump(mysqli_set_opt($link, MYSQLI_CLIENT_SSL, 'not an mysqli_option'));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_set_opt($link, MYSQLI_INIT_COMMAND, 'SET AUTOCOMMIT=1'));
+
+ print "done!";
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(true)
+bool(false)
+
+Warning: mysqli_set_opt(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_set_opt_numeric_and_datetime_as_unicode.phpt b/ext/mysqli/tests/mysqli_set_opt_numeric_and_datetime_as_unicode.phpt
new file mode 100644
index 0000000000..710ae70d3b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_set_opt_numeric_and_datetime_as_unicode.phpt
@@ -0,0 +1,148 @@
+--TEST--
+mysqli_set_opt() - MYSQLI_OPT_NUMERIC_AND_DATETIME_AS_UNICODE
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!function_exists('unicode_semantics'))
+ die("skip needs PHP 6");
+if (!unicode_semantics())
+ die("skip works only in unicode mode");
+if (!stristr(mysqli_get_client_info(), "mysqlnd"))
+ die("skip works only with mysqlnd");
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ include "table.inc";
+
+ if (true !== ($tmp = mysqli_set_opt($link, MYSQLI_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, 1)))
+ printf("[001] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, 'ALTER TABLE test ADD col_date DATE,
+ ADD col_time TIME,
+ ADD col_timestamp TIMESTAMP,
+ ADD col_datetime DATETIME'))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, 'UPDATE test SET col_date = NOW(),
+ col_time = NOW(),
+ col_timestamp = NOW(),
+ col_datetime = NOW()'))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_unicode($row['col_time']) || '' == $row['col_time'])
+ printf("[006] Expecting unicode/any, got %s/%s\n", gettype($row['col_time']), $row['col_time']);
+
+ if (!is_unicode($row['col_timestamp']) || '' == $row['col_timestamp'])
+ printf("[007] Expecting unicode/any, got %s/%s\n", gettype($row['col_timestamp']), $row['col_timestamp']);
+
+ if (!is_unicode($row['col_datetime']) || '' == $row['col_datetime'])
+ printf("[008] Expecting unicode/any, got %s/%s\n", gettype($row['col_datetime']), $row['col_datetime']);
+
+ if (!is_unicode($row['col_date']) || '' == $row['col_date'])
+ printf("[009] Expecting unicode/any, got %s/%s\n", gettype($row['col_date']), $row['col_date']);
+
+ mysqli_free_result($res);
+
+ if (true !== ($tmp = mysqli_set_opt($link, MYSQLI_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, 0)))
+ printf("[010] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (is_unicode($row['col_time']) || '' == $row['col_time'])
+ printf("[013] Expecting (binary) string/any, got %s/%s\n", gettype($row['col_time']), $row['col_time']);
+
+ if (is_unicode($row['col_timestamp']) || '' == $row['col_timestamp'])
+ printf("[014] Expecting (binary) string/any, got %s/%s\n", gettype($row['col_timestamp']), $row['col_timestamp']);
+
+ if (is_unicode($row['col_datetime']) || '' == $row['col_datetime'])
+ printf("[015] Expecting (binary) string/any, got %s/%s\n", gettype($row['col_datetime']), $row['col_datetime']);
+
+ if (is_unicode($row['col_date']) || '' == $row['col_date'])
+ printf("[016] Expecting (binary) string/any, got %s/%s\n", gettype($row['col_date']), $row['col_date']);
+
+ mysqli_free_result($res);
+
+ if (true !== ($tmp = mysqli_set_opt($link, MYSQLI_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, 1)))
+ printf("[017] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$res = mysqli_query($link, 'SELECT * FROM test'))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_unicode($row['col_time']) || '' == $row['col_time'])
+ printf("[020] Expecting unicode/any, got %s/%s\n", gettype($row['col_time']), $row['col_time']);
+
+ mysqli_free_result($res);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[021] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $col_date = $col_time = $col_datetime = $col_timestamp = null;
+ if (!mysqli_stmt_prepare($stmt, 'SELECT col_date, col_time, col_datetime, col_timestamp FROM test') ||
+ !mysqli_stmt_execute($stmt) ||
+ !mysqli_stmt_bind_result($stmt, $col_date, $col_time, $col_datetime, $col_timestamp) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_unicode($col_date) || '' == $col_date)
+ printf("[023] Expecting unicode/any, got %s/%s\n", gettype($col_date), $col_date);
+
+ if (!is_unicode($col_time) || '' == $col_time)
+ printf("[024] Expecting unicode/any, got %s/%s\n", gettype($col_time), $col_time);
+
+ if (!is_unicode($col_datetime) || '' == $col_datetime)
+ printf("[025] Expecting unicode/any, got %s/%s\n", gettype($col_datetime), $col_datetime);
+
+ if (!is_unicode($col_timestamp) || '' == $col_timestamp)
+ printf("[026] Expecting unicode/any, got %s/%s\n", gettype($col_timestamp), $col_timestamp);
+
+ mysqli_stmt_close($stmt);
+
+ if (true !== ($tmp = mysqli_set_opt($link, MYSQLI_OPT_NUMERIC_AND_DATETIME_AS_UNICODE, 0)))
+ printf("[027] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[028] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ $col_date = $col_time = $col_datetime = $col_timestamp = null;
+ if (!mysqli_stmt_prepare($stmt, 'SELECT col_date, col_time, col_datetime, col_timestamp FROM test') ||
+ !mysqli_stmt_execute($stmt) ||
+ !mysqli_stmt_bind_result($stmt, $col_date, $col_time, $col_datetime, $col_timestamp) ||
+ !mysqli_stmt_fetch($stmt))
+ printf("[029] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (is_unicode($col_date) || '' == $col_date)
+ printf("[030] Expecting (binary) string/any, got %s/%s\n", gettype($col_date), $col_date);
+
+ if (is_unicode($col_time) || '' == $col_time)
+ printf("[031] Expecting (binary) string/any, got %s/%s\n", gettype($col_time), $col_time);
+
+ if (is_unicode($col_datetime) || '' == $col_datetime)
+ printf("[032] Expecting (binary) string/any, got %s/%s\n", gettype($col_datetime), $col_datetime);
+
+ if (is_unicode($col_timestamp) || '' == $col_timestamp)
+ printf("[033] Expecting (binary) string/any, got %s/%s\n", gettype($col_timestamp), $col_timestamp);
+
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_slave_query.phpt b/ext/mysqli/tests/mysqli_slave_query.phpt
new file mode 100755
index 0000000000..1be22ac3fd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_slave_query.phpt
@@ -0,0 +1,50 @@
+--TEST--
+mysqli_slave_query()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_slave_query')) {
+ die("skip mysqli_slave_query() not available");
+}
+require_once('connect.inc');
+if (!$TEST_EXPERIMENTAL)
+ die("skip - experimental (= unsupported) feature");
+?>
+--FILE--
+<?php
+ /* NOTE: tests is a stub, but function is deprecated, as long as it does not crash when invoking it... */
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (NULL !== ($tmp = @mysqli_slave_query()))
+ printf("[001] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = @mysqli_slave_query($link)))
+ printf("[002] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("[003] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+
+ $query = array();
+ if (NULL !== ($tmp = @mysqli_slave_query($link, $query)))
+ printf("[004] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_int($tmp = mysqli_slave_query($link, 'SELECT 1')))
+ printf("[005] Expecting integer/any value, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_slave_query($link, 'SELECT 1')))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_slave_query(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_sqlstate.phpt b/ext/mysqli/tests/mysqli_sqlstate.phpt
new file mode 100644
index 0000000000..cdf0b5eecf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_sqlstate.phpt
@@ -0,0 +1,46 @@
+--TEST--
+mysqli_sqlstate()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_sqlstate()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_sqlstate($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ var_dump(@mysqli_sqlstate($link, "foo"));
+
+ var_dump(mysqli_sqlstate($link));
+ mysqli_query($link, "SELECT unknown_column FROM test");
+ var_dump(mysqli_sqlstate($link));
+ mysqli_free_result(mysqli_query($link, "SELECT id FROM test"));
+ var_dump(mysqli_sqlstate($link));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_sqlstate($link));
+
+ print "done!";
+?>
+--EXPECTF--
+NULL
+%s(5) "00000"
+%s(5) "42S22"
+%s(5) "00000"
+
+Warning: mysqli_sqlstate(): Couldn't fetch mysqli in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_ssl_set.phpt b/ext/mysqli/tests/mysqli_ssl_set.phpt
new file mode 100644
index 0000000000..c53cdf1384
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_ssl_set.phpt
@@ -0,0 +1,61 @@
+--TEST--
+mysqli_ssl_set() - test is a stub!
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+if (!function_exists('mysqli_ssl_set'))
+ die("skip function not available");
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_ssl_set()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link, $link, $link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_ssl_set($link, $link, $link, $link, $link)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ /*
+ This function always returns TRUE value.
+
+ $link = mysqli_init();
+ if (NULL !== ($tmp = @mysqli_ssl_set(
+ $link,
+ 'The path name to the key file.',
+ 'The path name to the certificate file.',
+ 'The path name to the certificate authority file.',
+ 'The pathname to a directory that contains trusted SSL CA certificates in PEM format.',
+ 'A list of allowable ciphers to use for SSL encryption.')))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+
+ If SSL setup is incorrect mysqli_real_connect()
+ will return an error when you attempt to connect.
+
+ ... and the above SSL setup should be always incorrect.
+
+ if (false !== ($tmp = mysqli_real_connect($link, $host, $user, $passwd, $db, $port, $socket)))
+ printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ */
+ print "done!\n";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_stat.phpt b/ext/mysqli/tests/mysqli_stat.phpt
new file mode 100644
index 0000000000..7d7d4e70ce
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stat.phpt
@@ -0,0 +1,40 @@
+--TEST--
+mysqli_stat()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stat()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stat($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stat($link, "foo")))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if ((!is_string($tmp = mysqli_stat($link))) || ('' === $tmp))
+ printf("[004] Expecting non empty string, got %s/'%s', [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysql_error($link));
+
+ mysqli_close($link);
+
+ if (!is_null($tmp = mysqli_stat($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stat(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
new file mode 100644
index 0000000000..5a8ce8af80
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_affected_rows.phpt
@@ -0,0 +1,183 @@
+--TEST--
+mysqli_stmt_affected_rows()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_affected_rows()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_affected_rows($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
+ printf("Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+ }
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'DROP TABLE IF EXISTS test') ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[003] Failed to drop old test table: [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!mysqli_stmt_prepare($stmt, 'CREATE TABLE test(id INT, label CHAR(1), PRIMARY KEY(id)) ENGINE = ' . $engine) ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[004] Failed to create test table: [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[005] Expecting int/0, got %s/'%s'\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id, label) VALUES (1, "a")') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id, label) VALUES (100, "z")') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[008] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id, label) VALUES (100, "z")') ||
+ !mysqli_stmt_execute($stmt))
+ // NOTE: the error message varies with the MySQL Server version, dump only the error code!
+ printf("[009] [%d] (error message varies with the MySQL Server version, check the error code)\n", mysqli_stmt_errno($stmt));
+
+ /* an error occured: affected rows should return -1 */
+ if (-1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[010] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id, label) VALUES (1, "a") ON DUPLICATE KEY UPDATE id = 4') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (2 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[012] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (2, 'b'), (3, 'c')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (2 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[014] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT IGNORE INTO test(id, label) VALUES (1, 'a')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[016] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!($res = mysqli_query($link, "SELECT count(id) AS num FROM test")) ||
+ !($tmp = mysqli_fetch_assoc($res)))
+ printf("[017] [%d] %s\n", mysqli_errnor($link), mysqli_error($link));
+ $num = (int)$tmp['num'];
+ mysqli_free_result($res);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) SELECT id + 10, label FROM test") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ($num !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[019] Expecting int/%d, got %s/%s\n", $num, gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "REPLACE INTO test(id, label) values (4, 'd')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[020] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (2 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[021] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "REPLACE INTO test(id, label) values (5, 'e')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[023] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'a' WHERE id = 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[024] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[025] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'a' WHERE id = 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[026] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (0 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[027] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "UPDATE test SET label = 'a' WHERE id = 100") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[028] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (1 !== ($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[029] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[030] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!is_null($tmp = mysqli_stmt_affected_rows($stmt)))
+ printf("[031] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+[009] [%d] (error message varies with the MySQL Server version, check the error code)
+
+Warning: mysqli_stmt_affected_rows(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_attr_get.phpt b/ext/mysqli/tests/mysqli_stmt_attr_get.phpt
new file mode 100644
index 0000000000..d17e736f05
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_attr_get.phpt
@@ -0,0 +1,66 @@
+--TEST--
+mysqli_stmt_attr_get()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stmt_attr_get($link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $valid_attr = array("max_length" => MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
+ if (mysqli_get_client_version() > 50003)
+ $valid_attr["cursor_type"] = MYSQLI_STMT_ATTR_CURSOR_TYPE;
+
+ if ($IS_MYSQLND && mysqli_get_client_version() > 50007)
+ $valid_attr["prefetch_rows"] = MYSQLI_STMT_ATTR_PREFETCH_ROWS;
+
+ do {
+ $invalid_attr = mt_rand(0, 10000);
+ } while (in_array($invalid_attr, $valid_attr));
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, 'SELECT * FROM test');
+ if (false !== ($tmp = @mysqli_stmt_attr_get($stmt, $invalid_attr)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ foreach ($valid_attr as $k => $attr) {
+ if (false === ($tmp = mysqli_stmt_attr_get($stmt, $attr))) {
+ printf("[006] Expecting any type, but not boolean/false, got %s/%s for attribute %s/%s\n",
+ gettype($tmp), $tmp, $k, $attr);
+ }
+ }
+
+ $stmt->close();
+
+ foreach ($valid_attr as $k => $attr) {
+ if (!is_null($tmp = @mysqli_stmt_attr_get($stmt, $attr))) {
+ printf("[007] Expecting NULL/NULL, got %s/%s for attribute %s/%s\n",
+ gettype($tmp), $tmp, $k, $attr);
+ }
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt b/ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt
new file mode 100644
index 0000000000..cb7d507eb8
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_attr_get_prefetch.phpt
@@ -0,0 +1,26 @@
+--TEST--
+mysqli_stmt_attr_get() - prefetch
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+die("SKIP: prefetch isn't supported at the moment");
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ mysqli_stmt_prepare($stmt, 'SELECT * FROM test');
+ if (1 !== ($tmp = mysqli_stmt_attr_get($stmt, MYSQLI_STMT_ATTR_PREFETCH_ROWS))) {
+ printf("[001] Expecting int/1, got %s/%s for attribute %s/%s\n",
+ gettype($tmp), $tmp, $k, $attr);
+ }
+ $stmt->close();
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_attr_set.phpt b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt
new file mode 100644
index 0000000000..c1959afed6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_attr_set.phpt
@@ -0,0 +1,263 @@
+--TEST--
+mysqli_stmt_attr_set()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set($link, $link)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_attr_set($link, $link, $link)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $valid_attr = array(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH);
+ if ((mysqli_get_client_version() > 50003) || $IS_MYSQLND) {
+ $valid_attr[] = MYSQLI_STMT_ATTR_CURSOR_TYPE;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_NO_CURSOR;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_READ_ONLY;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_FOR_UPDATE;
+ $valid_attr[] = MYSQLI_CURSOR_TYPE_SCROLLABLE;
+ }
+
+ if ((mysqli_get_client_version() > 50007) || $IS_MYSQLND)
+ $valid_attr[] = MYSQLI_STMT_ATTR_PREFETCH_ROWS;
+
+
+ $stmt = mysqli_stmt_init($link);
+ if (!is_null($tmp = @mysqli_stmt_attr_set($stmt, 0, 0)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt->prepare("SELECT * FROM test");
+ mt_srand(microtime(true));
+ for ($i = -100; $i < 1000; $i++) {
+ if (in_array($i, $valid_attr))
+ continue;
+ $invalid_attr = $i;
+ if (false !== ($tmp = @mysqli_stmt_attr_set($stmt, $invalid_attr, 0)))
+ printf("[006a] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp);
+ }
+
+ for ($i = 0; $i < 10; $i++) {
+ do {
+ $invalid_attr = mt_rand(-1 * PHP_INT_MAX + 1, PHP_INT_MAX);
+ } while (in_array($invalid_attr, $valid_attr));
+ if (false !== ($tmp = @mysqli_stmt_attr_set($stmt, $invalid_attr, 0)))
+ printf("[006b] Expecting boolean/false for attribute %d, got %s/%s\n", $invalid_attr, gettype($tmp), $tmp);
+ }
+ $stmt->close();
+
+ //
+ // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH
+ //
+
+
+ // expecting max_length not to be set and be 0 in all cases
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ $stmt->execute();
+ $stmt->store_result();
+ $res = $stmt->result_metadata();
+ $fields = $res->fetch_fields();
+ $max_lengths = array();
+ foreach ($fields as $k => $meta) {
+ $max_lengths[$meta->name] = $meta->max_length;
+ if ($meta->max_length !== 0)
+ printf("[007] max_length should be not set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
+ }
+ $res->close();
+ $stmt->close();
+
+ // expecting max_length to _be_ set
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1);
+ $stmt->execute();
+ $stmt->store_result();
+ $res = $stmt->result_metadata();
+ $fields = $res->fetch_fields();
+ $max_lengths = array();
+ foreach ($fields as $k => $meta) {
+ $max_lengths[$meta->name] = $meta->max_length;
+ if ($meta->max_length === 0)
+ printf("[008] max_length should be set (!= 0), got %s for field %s\n", $meta->max_length, $meta->name);
+ }
+ $res->close();
+ $stmt->close();
+
+ // expecting max_length not to be set
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 0);
+ $stmt->execute();
+ $stmt->store_result();
+ $res = $stmt->result_metadata();
+ $fields = $res->fetch_fields();
+ $max_lengths = array();
+ foreach ($fields as $k => $meta) {
+ $max_lengths[$meta->name] = $meta->max_length;
+ if ($meta->max_length !== 0)
+ printf("[009] max_length should not be set (= 0), got %s for field %s\n", $meta->max_length, $meta->name);
+ }
+ $res->close();
+ $stmt->close();
+
+ //
+ // Cursors
+ //
+
+ if (mysqli_get_client_version() > 50003) {
+
+ $cursor_types = array(
+ MYSQLI_CURSOR_TYPE_NO_CURSOR,
+ MYSQLI_CURSOR_TYPE_READ_ONLY,
+ MYSQLI_CURSOR_TYPE_FOR_UPDATE,
+ MYSQLI_CURSOR_TYPE_SCROLLABLE
+ );
+ do {
+ $invalid_cursor_type = mt_rand(-1000, 1000);
+ } while (in_array($invalid_cursor_type, $cursor_types));
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+
+ if (false !== ($tmp = @$stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, $invalid_cursor_type)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE)))
+ printf("[011] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_SCROLLABLE)))
+ printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR)))
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY)))
+ printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt->close();
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results = array();
+ while ($stmt->fetch())
+ $results[$id] = $label;
+ $stmt->close();
+ if (empty($results))
+ printf("[015] Results should not be empty, subsequent tests will probably fail!\n");
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR)))
+ printf("[016] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results2 = array();
+ while ($stmt->fetch())
+ $results2[$id] = $label;
+ $stmt->close();
+ if ($results != $results2) {
+ printf("[017] Results should not differ. Dumping both result sets.\n");
+ var_dump($results);
+ var_dump($results2);
+ }
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY)))
+ printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results2 = array();
+ while ($stmt->fetch())
+ $results2[$id] = $label;
+ $stmt->close();
+ if ($results != $results2) {
+ printf("[019] Results should not differ. Dumping both result sets.\n");
+ var_dump($results);
+ var_dump($results2);
+ }
+
+ }
+
+
+ //
+ // MYSQLI_STMT_ATTR_PREFETCH_ROWS
+ //
+
+ if (mysqli_get_client_version() > 50007) {
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 1)))
+ printf("[020] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results = array();
+ while ($stmt->fetch())
+ $results[$id] = $label;
+ $stmt->close();
+ if (empty($results))
+ printf("[021] Results should not be empty, subsequent tests will probably fail!\n");
+
+ /* prefetch is not supported
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, -1)))
+ printf("[022] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->close();
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, PHP_INT_MAX)))
+ printf("[023] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->close();
+
+ $stmt = mysqli_stmt_init($link);
+ $stmt->prepare("SELECT id, label FROM test");
+ if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 2)))
+ printf("[024] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ $stmt->execute();
+ $id = $label = NULL;
+ $stmt->bind_result($id, $label);
+ $results2 = array();
+ while ($stmt->fetch())
+ $results2[$id] = $label;
+ $stmt->close();
+ if ($results != $results2) {
+ printf("[025] Results should not differ. Dumping both result sets.\n");
+ var_dump($results);
+ var_dump($results2);
+ }
+ */
+
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt
new file mode 100644
index 0000000000..0b39a1b6d6
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param.phpt
@@ -0,0 +1,398 @@
+--TEST--
+mysqli_stmt_bind_param()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ /*
+ The way we test the INSERT and data types overlaps with
+ the mysqli_stmt_bind_result test in large parts. There is only
+ one difference. This test uses mysqli_query()/mysqli_fetch_assoc() to
+ fetch the inserted values. This way we test
+ mysqli_query()/mysqli_fetch_assoc() for all possible data types
+ in this file and we test mysqli_stmt_bind_result() in the other
+ test -- therefore the "duplicate" makes some sense to me.
+ */
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_bind_param()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_bind_param($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_bind_param($link, $link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+
+ /*
+ libmysql gives a less descriptive error message but mysqlnd,
+ we did not unify the error messages but ignore this slight difference silently
+ */
+ if (!false === ($tmp = @mysqli_stmt_bind_param($stmt, " ", $tmp)))
+ printf("[003d] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = @mysqli_stmt_bind_param($stmt, "", $id, $label)))
+ printf("[003a] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ /* TODO: somehwhat undocumented syntax! */
+ $param = array($id);
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param)))
+ printf("[003b] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ $param = array($id, $label, $id);
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "is", $param)))
+ printf("[003c] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id)))
+ printf("[004] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "a", $id, $label)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "aa", $id, $label)))
+ printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!false === ($tmp = mysqli_stmt_bind_param($stmt, "ia", $id, $label)))
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!true === ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (function_exists("memory_get_usage")) {
+ $mem = memory_get_usage();
+ for ($i = 0; $i < 20000; $i++) {
+ if (!true === ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[008][$i] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ }
+ if (($tmp = (memory_get_usage() - $mem)) > 600)
+ printf("[009] Function seems to be leaking, because it used %d bytes. During tests it used only 92 bytes.", $tmp);
+ }
+
+ $id = 100;
+ $label = "z";
+ if (!mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!($res = mysqli_query($link, "SELECT id, label FROM test WHERE id = " . $id)))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ $row = mysqli_fetch_assoc($res);
+ if (($row['id'] != $id) || ($row['label'] != $label))
+ printf("[012] Expecting '%s'/%s', got '%s'/%s'!\n", $id, $label, $row['id'], $row['label']);
+ mysqli_free_result($res);
+
+ function func_mysqli_stmt_bind_datatype($link, $engine, $bind_type, $sql_type, $bind_value, $offset, $alternative = null) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) {
+ // don't bail - it might be that the server does not support the data type
+ return false;
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%03d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUE (?, ?)")) {
+ printf("[%03d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $id = 1;
+ if (!mysqli_stmt_bind_param($stmt, "i" . $bind_type, $id, $bind_value)) {
+ printf("[%03d] [%d] %s\n", $offset + 3, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d] [%d] %s\n", $offset + 4, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ mysqli_stmt_close($stmt);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test")) {
+ printf("[%03d] [%d] %s\n", $offset + 5, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[%03d] [%d] %s\n", $offset + 5, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if ($alternative) {
+ if (($row['id'] != $id) || (($row['label'] != $bind_value) && ($row['label'] != $alternative))) {
+ printf("[%03d] Testing '%s', '%s': expecting '%s'/'%s' (%s), got '%s'/'%s'\n",
+ $offset + 6, $bind_type, $sql_type,
+ $id, $bind_value, gettype($bind_value), $row['id'], $row['label']);
+ return false;
+ }
+ } else {
+ if (($row['id'] != $id) || ($row['label'] != $bind_value)) {
+ printf("[%03d] Testing '%s', '%s': expecting '%s'/'%s', got '%s'/'%s'\n",
+ $offset + 6, $bind_type, $sql_type,
+ $id, $bind_value, $row['id'], $row['label']);
+ return false;
+ }
+ }
+
+ mysqli_free_result($res);
+ 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_bind_datatype($link, $engine, "i", "TINYINT", -11, 20);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT", NULL, 30);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT UNSIGNED", 1, 40);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "TINYINT UNSIGNED", NULL, 50);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOL", 1, 60);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOL", NULL, 70);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOLEAN", 0, 80);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BOOLEAN", NULL, 90);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT", -32768, 100);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT", 32767, 110);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT", NULL, 120);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 130);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 140);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT", -8388608, 150);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT", 8388607, 160);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT", NULL, 170);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT UNSIGNED", 16777215, 180);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "MEDIUMINT UNSIGNED", NULL, 190);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER", -2147483648, 200);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER", 2147483647, 210);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER", NULL, 220);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, PHP_INT_MAX) : 1, 230);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "INTEGER UNSIGNED", 4294967295, 240);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "INTEGER UNSIGNED", NULL, 250);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 260);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT", NULL, 270);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT", PHP_INT_MAX, 280);
+ func_mysqli_stmt_bind_datatype($link, $engine, "i", "BIGINT UNSIGNED", NULL, 290);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BIGINT", "-9223372036854775808", 900);
+ // ?? func_mysqli_stmt_bind_datatype($link, $engine, "d", "BIGINT", -9223372036854775808, 910);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 920);
+
+/*
+ ??
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 300);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 320);
+ */
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", NULL, 310);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 330);
+ if (2147483647 == PHP_INT_MAX) {
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED", PHP_INT_MAX, 930, '2.14748e+09');
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", -1 * PHP_INT_MAX + 1, 940, '-2.14748e+09');
+ }
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "FLOAT", "-9223372036854775808", 300, '-9.22337e+18');
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "FLOAT UNSIGNED", "18446744073709551615", 320, '1.84467e+19');
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT", -10.01, 950);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "FLOAT UNSIGNED", 10.01, 960);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2)", NULL, 350);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 370);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2)", -99999999.99, 340);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", 99999999.99, 360);
+
+ /*
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2)", -99999999.99, 340);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", 99999999.99, 360);
+ */
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", -99999999.99, 380);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", NULL, 390);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", 99999999.99, 400);
+ func_mysqli_stmt_bind_datatype($link, $engine, "d", "DECIMAL(10,2)", NULL, 410);
+
+ // don't care about date() strict TZ warnings...
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATE", @date('Y-m-d'), 420);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 430);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATE", NULL, 440);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 450);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 460);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "DATETIME", NULL, 470);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 480);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME", @date('H:i:s'), 490);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 500);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TIME", NULL, 510);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "YEAR", @date('Y'), 520);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "YEAR NOT NULL", @date('Y'), 530);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "YEAR", NULL, 540);
+
+ $string255 = func_mysqli_stmt_bind_make_string(255);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(1)", "a", 550);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(255)", $string255, 560);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(1) NOT NULL", "a", 570);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "CHAR(1)", NULL, 580);
+
+ $string65k = func_mysqli_stmt_bind_make_string(65535);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(1)", "a", 590);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(255)", $string255, 600);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(65635)", $string65k, 610);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 620);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARCHAR(1)", NULL, 630);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1)", "a", 640);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1)", chr(0), 650);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1) NOT NULL", "b", 660);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "BINARY(1)", NULL, 670);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1)", "a", 680);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1)", chr(0), 690);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 700);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "VARBINARY(1)", NULL, 710);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB", "a", 720);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB", chr(0), 730);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB NOT NULL", "b", 740);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYBLOB", NULL, 750);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYTEXT", "a", 760);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYTEXT NOT NULL", "a", 770);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "TINYTEXT", NULL, 780);
+
+ // 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_bind_datatype($link, $engine, "b", "BLOB", "", 790);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "TEXT", "", 800);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "MEDIUMBLOB", "", 810);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "MEDIUMTEXT", "", 820);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "LONGBLOB", "", 830);
+ func_mysqli_stmt_bind_datatype($link, $engine, "b", "LONGTEXT", "", 840);
+
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "ENUM('a', 'b')", "a", 850);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "ENUM('a', 'b')", NULL, 860);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "SET('a', 'b')", "a", 870);
+ func_mysqli_stmt_bind_datatype($link, $engine, "s", "SET('a', 'b')", NULL, 880);
+
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[2000] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[2001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_execute($stmt);
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[2002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+ include("table.inc");
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[2003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[2004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (true !== ($tmp = $stmt->bind_param('is', $id, $label)))
+ printf("[2005] Expecting boolean/true got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp,
+ $stmt->errno, $stmt->error);
+
+ $id = 100; $label = 'z';
+ if (!$stmt->execute())
+ printf("[2006] [%d] %s\n", $stmt->errno, $stmt->error);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test WHERE id = 100"))
+ printf("[2007] Expecting record 100/z, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[2008] Expecting row, [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if ($row['id'] != 100 || $row['label'] != 'z') {
+ printf("[2009] Row seems wrong, dumping record\n");
+ var_dump($row);
+ }
+ mysqli_free_result($res);
+
+ $value_list = array(array('id' => 101, 'label' => 'a'), array('id' => 102, 'label' => 'b'));
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[2010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ foreach ($value_list as $k => $values) {
+ if (!mysqli_stmt_bind_param($stmt, 'is', $values['id'], $values['label'])) {
+ printf("[2011] bind_param() failed for id = %d, [%d] %s\n",
+ $values['id'], mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ continue;
+ }
+ if (!$stmt->execute())
+ printf("[2012] [%d] execute() failed for id = %d, [%d] %s\n",
+ $values['id'], mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, sprintf("SELECT label FROM test WHERE id = %d", $values['id'])))
+ printf("[2013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[2014] Cannot find row id = %d\n", $values['id']);
+ else if (isset($row['label']) && ($values['label'] != $row['label']))
+ printf("[2015] Expecting label = %s, got label = %s\n", $values['label'], $row['label']);
+
+ mysqli_free_result($res);
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_bind_param()))
+ printf("[021] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of variables doesn't match number of parameters in prepared statement in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Number of elements in type definition string doesn't match number of bind variables in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Undefined fieldtype a (parameter 3) in %s on line %d
+
+Warning: mysqli_stmt_bind_param(): Undefined fieldtype a (parameter 4) in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt
new file mode 100644
index 0000000000..8ca45691e5
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_references.phpt
@@ -0,0 +1,203 @@
+--TEST--
+mysqli_stmt_bind_param() - playing with references
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ require('table.inc');
+
+ function findRow($offset, $link, $id, $label) {
+
+ $sql = sprintf("SELECT id, label FROM test WHERE id = '%d' AND label = '%s'",
+ $id, $label);
+ if (!$res = mysqli_query($link, $sql)) {
+ printf("[%03d + 1] %s failed, [%d] %s\n",
+ $offset, $sql, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ if (!$row = mysqli_fetch_assoc($res)) {
+ printf("[%03d + 2] fetch for %s failed, [%d] %s\n",
+ $offset, $sql, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ mysqli_free_result($res);
+ if ($row['id'] != $id) {
+ printf("[%03d + 3] Expecting %s/%s got %s/%s\n",
+ $offset, gettype($id), $id,
+ gettype($row['id']), $row['id']
+ );
+ return false;
+ }
+
+ if ($row['label'] != $label) {
+ printf("[%03d + 4] Expecting %s/%s got %s/%s\n",
+ $offset, gettype($label), $label,
+ gettype($row['label']), $row['label']
+ );
+ return false;
+ }
+
+ $sql = sprintf("DELETE FROM test WHERE id = '%d' AND label = '%s'",
+ $id, $label);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d + 5] %s failed, [%d] %s\n",
+ $offset, $sql, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ return true;
+ }
+ // or we will get dups around [28]
+ mysqli_query($link, "ALTER TABLE test DROP PRIMARY KEY");
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 100;
+ $label = 'v';
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[002] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ // no need to check the return value, will bail and make EXPECTF fail if need be
+ findRow(4, $link, $id, $label);
+
+ $id++;
+ $label_ref = &$label;
+ $label = 'w';
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_ref)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(7, $link, $id, $label_ref);
+
+ $id++;
+ $label_ref_ref = &$label_ref;
+ $label = 'x';
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_ref_ref)))
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(9, $link, $id, $label_ref_ref);
+
+ $id = 9;
+ $label = $id;
+ $label_num = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_num)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(12, $link, $id, $label_num);
+
+ $label_num = &$id;
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_num)))
+ printf("[013] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(15, $link, $id, $label_num);
+
+ $label = 9;
+ $id = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[015] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(17, $link, $id, $label);
+
+ $base = 9;
+ $id = &$base;
+ $label = &$id;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[018] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(20, $link, $id, $label);
+
+ $id_ref = &$id;
+ $label_ref = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id_ref, $label_ref)))
+ printf("[021] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(23, $link, $id_ref, $label_ref);
+
+ $id_ref_ref = &$GLOBALS['id_ref'];
+ $label_ref_ref = &$GLOBALS['label_ref_ref'];
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id_ref_ref, $label_ref_ref)))
+ printf("[024] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[025] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(26, $link, $id_ref_ref, $label_ref_ref);
+
+ $id = 102;
+ $label = new stdClass();
+ $label->label = 'y';
+ $id_ref = &$GLOBALS['id'];
+ $label_ref = &$label->label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id_ref, $label_ref)))
+ printf("[027] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+ if (true !== @mysqli_stmt_execute($stmt))
+ printf("[028] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(29, $link, $id_ref, $label_ref);
+
+ $id = 103;
+ $label_a = &$label_b;
+ $label_b = &$label_a;
+ $label_a = 'z';
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label_b)))
+ printf("[030] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[031] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(32, $link, $id, $label_b);
+
+ class foo {
+ public $foo;
+ function foo() {
+ $this->foo = &$this->bar;
+ }
+ }
+ class bar extends foo {
+ public $bar = 'v';
+ }
+ $bar = new bar();
+ $id++;
+ $label = &$GLOBALS['bar']->foo;
+
+ if (true !== ($tmp = mysqli_stmt_bind_param($stmt, "is", $id, $label)))
+ printf("[033] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ findRow(35, $link, $id, $label);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt b/ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt
new file mode 100644
index 0000000000..e9c3ad450e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_param_type_juggling.phpt
@@ -0,0 +1,126 @@
+--TEST--
+mysqli_stmt_bind_param() - binding variable twice
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ require('table.inc');
+
+ function bind_twice($link, $engine, $sql_type1, $sql_type2, $bind_type1, $bind_type2, $bind_value1, $bind_value2, $offset) {
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) {
+ printf("[%03d + 1] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ mysqli_autocommit($link, true);
+
+ $sql = sprintf("CREATE TABLE test(col1 %s, col2 %s) ENGINE=%s", $sql_type1, $sql_type2, $engine);
+ if (!mysqli_query($link, $sql)) {
+ printf("[%03d + 2] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%03d + 3] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(col1, col2) VALUES (?, ?)")) {
+ printf("[%03d + 4] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_bind_param($stmt, $bind_type1 . $bind_type2, $bind_value1, $bind_value1)) {
+ printf("[%03d + 5] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d + 6] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_bind_param($stmt, $bind_type1 . $bind_type2, $bind_value1, $bind_value2)) {
+ printf("[%03d + 7] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d + 8] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ mysqli_stmt_close($stmt);
+ if (!$res = mysqli_query($link, "SELECT col1, col2 FROM test")) {
+ printf("[%03d + 9] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (2 !== ($tmp = mysqli_num_rows($res))) {
+ printf("[%03d + 10] Expecting 2 rows, got %d rows [%d] %s\n", $offset, $tmp, mysqli_errno($link), mysqli_error($link));
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ if (($row['col1'] != $bind_value1) || ($row['col2'] != $bind_value1)) {
+ printf("[%03d + 11] Expecting col1 = %s, col2 = %s got col1 = %s, col2 = %s - [%d] %s\n",
+ $offset, $bind_value1, $bind_value1,
+ $row['col1'], $row['col2'],
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ $row = mysqli_fetch_assoc($res);
+ if (($row['col1'] != $bind_value1) || ($row['col2'] != $bind_value2)) {
+ printf("[%03d + 12] Expecting col1 = %s, col2 = %s got col1 = %s, col2 = %s - [%d] %s\n",
+ $offset, $bind_value1, $bind_value2,
+ $row['col1'], $row['col2'],
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+ mysqli_free_result($res);
+ return true;
+ }
+
+ bind_twice($link, $engine, 'CHAR(1)', 'CHAR(1)', 's', 's', 'a', 'b', 10);
+ bind_twice($link, $engine, 'INT', 'INT', 'i', 'i', 1, 2, 20);
+ bind_twice($link, $engine, 'FLOAT', 'FLOAT', 'd', 'd', 1.01, 1.02, 30);
+
+ /* type juggling - note that int->char works */
+ bind_twice($link, $engine, 'CHAR(1)', 'CHAR(1)', 's', 's', 1, 2, 40);
+ /* type juggling - note that string->integer works */
+ bind_twice($link, $engine, 'INT', 'INT', 'i', 'i', '1', '2', 50);
+ /* type juggling - note that string->float works*/
+ bind_twice($link, $engine, 'FLOAT', 'FLOAT', 'd', 'd', '1.01', '1.02', 60);
+
+ /* now, let's have two columns of different type and do type juggling */
+ /*
+ what the test will do is:
+ 1) col1 INT, col2 CHAR(1)
+ 2) bind_param('is', 1, 1)
+ 3) execute()
+ 4) bind_param('is', 1, 'a')
+ 5) execute()
+
+ col1 INT, col2 INT
+ bind_param('ii', '1', '2') --> OK (int column, string value)
+ bind_param('ii', 1, 2) --> OK (int column, int value)
+ col1 CHAR(1), col2 CHAR(2)
+ bind_param('ss', 1, 2) --> OK (string column, int value)
+
+ So, what about:
+ col1 INT, COL2 CHAR(1)
+ bind_param('is', 1, 1) ---> ??
+ */
+ bind_twice($link, $engine, 'INT', 'CHAR(1)', 'i', 's', 1, 'a', 70);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done!
+--UEXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result.phpt
new file mode 100644
index 0000000000..f5f08ac672
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result.phpt
@@ -0,0 +1,330 @@
+--TEST--
+mysqli_stmt_bind_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $hint_str_or_unicode = ini_get("unicode.semantics")? "unicode":"string";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_bind_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_bind_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[002a] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_null($tmp = @mysqli_stmt_bind_result($stmt)))
+ printf("[002b] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ $stmt = mysqli_stmt_init($link);
+
+ $id = null;
+ $label = null;
+ $foo = null;
+
+ if (!is_null($tmp = mysqli_stmt_bind_result($stmt)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id)))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label, $foo)))
+ printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ while (mysqli_stmt_fetch($stmt)) {
+ var_dump($id);
+ var_dump($label);
+ }
+ mysqli_stmt_close($stmt);
+
+
+ function func_mysqli_stmt_bind_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);
+
+ $bind_res = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $bind_res)) {
+ 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 (mysqli_stmt_fetch($stmt)) {
+ 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_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_stmt_close($stmt);
+ return false;
+ }
+
+ 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_bind_result($link, $engine, "i", "TINYINT", -11, 20);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", NULL, 40);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", 1, 60);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", NULL, 80);
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", 1, 100);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", NULL, 120);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", 0, 140);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", NULL, 160);
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", -32768, 180);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", 32767, 200);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", NULL, 220);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 240);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 260);
+
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", -8388608, 280, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", 8388607, 300, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", NULL, 320);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", 16777215, 340, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", NULL, 360);
+
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? max(-1 * PHP_INT_MAX + 1, -2147483648) : 1, 380);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", -2147483647, 400, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? min(2147483647, PHP_INT_MAX) : 1, 420);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", NULL, 440);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, 2147483647) : 1, 460);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", 4294967295, 480, (defined("PHP_INT_MAX") && (4294967295 > PHP_INT_MAX)) ? "string" : null);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", NULL, 500);
+
+ /* test is broken too: we bind "integer" but value is a float
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -9223372036854775808, 520);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 18446744073709551615, 560);
+ */
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", NULL, 540);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", NULL, 580);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1, 1780);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 1, 1800);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 1820);
+ func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", PHP_INT_MAX, 1840);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 1860);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BIGINT", "-9223372036854775808", 1880);
+
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 600);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", NULL, 620);
+ func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 640);
+ func_mysqli_stmt_bind_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_bind_result($link, $engine, "d", "DOUBLE(10,2)", $tmp, 680, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", NULL, 700);
+ $tmp = strval('99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", $tmp , 720, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 740);
+ $tmp = strval('-99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 760, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 780);
+ $tmp = strval('99999999.99');
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 800, "string");
+ func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 820);
+
+ // don't care about date() strict TZ warnings...
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", @date('Y-m-d'), 840);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 860);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", NULL, 880);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 900);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 920);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", NULL, 940);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 960);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", @date('H:i:s'), 980);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 1000);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", NULL, 1020);
+
+ $tmp = intval(@date('Y'));
+ func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", $tmp, 1040, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR NOT NULL", $tmp, 1060, "integer");
+ func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", NULL, 1080);
+
+ $string255 = func_mysqli_stmt_bind_make_string(255);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", "a", 1110, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(255)", $string255, 1120, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1) NOT NULL", "a", 1140, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", NULL, 1160);
+
+ $string65k = func_mysqli_stmt_bind_make_string(65535);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", "a", 1180, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(255)", $string255, 1200, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(65635)", $string65k, 1220, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 1240, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", NULL, 1260);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", "a", 1280);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", chr(0), 1300);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1) NOT NULL", "b", 1320);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", NULL, 1340);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", "a", 1360);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", chr(0), 1380);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 1400);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", NULL, 1420);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", "a", 1440);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", chr(0), 1460);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB NOT NULL", "b", 1480);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", NULL, 1500);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", "a", 1520, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT NOT NULL", "a", 1540, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_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_bind_result($link, $engine, "b", "BLOB", b"", 1580);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "TEXT", "", 1600, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMBLOB", b"", 1620);
+ func_mysqli_stmt_bind_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_bind_result($link, $engine, "b", "LONGBLOB", "", 1660);
+ func_mysqli_stmt_bind_result($link, $engine, "b", "LONGTEXT", "", 1680, $hint_str_or_unicode);
+
+ func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", "a", 1700, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", NULL, 1720, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", "a", 1740, $hint_str_or_unicode);
+ func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", NULL, 1760, $hint_str_or_unicode);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_bind_result()))
+ printf("[3000] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (1000, 'z')"))
+ printf("[3001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ if (false !== @mysqli_stmt_bind_result($stmt, $id))
+ printf("[3002] Bind result should not be allowed");
+
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_bind_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d
+
+Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d
+int(1)
+%s(1) "a"
+done!
+--UEXPECTF--
+Warning: mysqli_stmt_bind_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d
+
+Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d
+int(1)
+unicode(1) "a"
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt
new file mode 100644
index 0000000000..4934177182
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_bit.phpt
@@ -0,0 +1,157 @@
+--TEST--
+mysqli_stmt_bind_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ function dec32bin($dec, $bits) {
+
+ $maxval = pow(2, $bits);
+ $bin = '';
+ for ($bitval = $maxval; $bitval >= 1; $bitval = $bitval / 2) {
+ if (($dec / $bitval) >= 1) {
+ $bin .= '1';
+ $dec -= $bitval;
+ } else {
+ $bin .= '0';
+ }
+ }
+ return $bin;
+ }
+
+ if (!$link_ins = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$link_sel = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[002] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ for ($bits = 1; $bits <= 46; $bits++) {
+
+ if (1 == $bits)
+ $max_value = 1;
+ else
+ $max_value = pow(2, $bits) - 1;
+
+ if (!mysqli_query($link_ins, "DROP TABLE IF EXISTS test")) {
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link_ins), mysqli_error($link_ins));
+ }
+
+ if (!mysqli_query($link_ins, sprintf("CREATE TABLE test(id BIGINT, bit_value BIT(%d) NOT NULL, bit_null BIT(%d) DEFAULT NULL) ENGINE = %s", $bits, $bits, $engine))) {
+ // don't bail - column type might not be supported by the server, ignore this
+ continue;
+ }
+ if (!$stmt_ins = mysqli_stmt_init($link_ins)) {
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_errno($link_ins), mysqli_error($link_ins));
+ continue;
+ }
+
+ if (!mysqli_stmt_prepare($stmt_ins, "INSERT INTO test(id, bit_value) VALUES (?, ?)")) {
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_ins), mysqli_stmt_error($stmt_ins));
+ mysqli_stmt_close($stmt_ins);
+ continue;
+ }
+
+ if (!($stmt_sel = mysqli_stmt_init($link_sel))) {
+ printf("[006 - %d] [%d] %s\n", $bits, mysqli_errno($link_sel), mysqli_error($link_sel));
+ mysqli_stmt_close($stmt_ins);
+ continue;
+ }
+
+ $tests = 0;
+ $rand_max = mt_getrandmax();
+ while ($tests < 10) {
+
+ $tests++;
+ if (1 == $tests)
+ $value = 0;
+ else if (2 == $tests)
+ $value = $max_value;
+ else {
+ if ($max_value > $rand_max) {
+ $max_loops = floor($max_value/$rand_max);
+ $num_loops = mt_rand(1, $max_loops);
+ $value = 0;
+ for ($i = 0; $i < $num_loops; $i++)
+ $value += mt_rand(0, $rand_max);
+ } else {
+ $value = mt_rand(0, $max_value);
+ }
+ }
+
+ $bin = ($bits < 32) ? decbin($value) : dec32bin($value, $bits);
+ for ($i = 0; ($i < strlen($bin)) && ($bin[$i] == '0'); $i++)
+ ;
+ $bin2 = substr($bin, $i, strlen($bin));
+
+ if (!mysqli_stmt_bind_param($stmt_ins, "dd", $value, $value)) {
+ printf("[007 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_ins), mysqli_stmt_error($stmt_ins));
+ mysqli_stmt_close($stmt_ins);
+ continue;
+ }
+ if (!mysqli_stmt_execute($stmt_ins)) {
+ printf("[008 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_ins), mysqli_stmt_error($stmt_ins));
+ break;
+ }
+ $sql = sprintf("SELECT id, BIN(bit_value) AS _bin, bit_value, bit_value + 0 AS _bit_value0, bit_null FROM test WHERE id = %s", $value);
+ if ((!mysqli_stmt_prepare($stmt_sel, $sql)) ||
+ (!mysqli_stmt_execute($stmt_sel))) {
+ printf("[009 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_sel), mysqli_stmt_error($stmt_sel));
+ break;
+ }
+
+ $row = array('id' => -1, '_bin' => - 1, 'bit_value' => -1, '_bit_value0' => -1, 'bit_null' => -1);
+ if (!mysqli_stmt_bind_result($stmt_sel, $row['id'], $row['_bin'], $row['bit_value'], $row['_bit_value0'], $row['bit_null'])) {
+ printf("[010 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt_sel), mysqli_stmt_error($stmt_sel));
+ break;
+ }
+
+ if (!($ret = mysqli_stmt_fetch($stmt_sel))) {
+ printf("[011 - %d] mysqli_stmt_fetch() has failed for %d bits - ret = %s/%s, [%d] %s, [%d] %s\n",
+ $bits, $bits,
+ gettype($ret), $ret,
+ mysqli_stmt_errno($stmt_sel), mysqli_stmt_error($stmt_sel),
+ mysqli_errno($link_sel), mysqli_errno($link_sel)
+ );
+ break;
+ }
+
+ if (($value != $row['id']) || (($bin != $row['_bin']) && ($bin2 != $row['_bin']))) {
+ debug_zval_dump($row);
+ printf("[012 - %d] Insert of %s in BIT(%d) column might have failed. id = %s, bin = %s (%s/%s)\n",
+ $bits, $value, $bits, $row['id'], $row['_bin'], $bin, $bin2);
+ break;
+ }
+ if ($value != $row['bit_value']) {
+ debug_zval_dump($row);
+ printf("[013 - %d] Expecting %s got %s\n", $bits, $value, $row['bit_value']);
+ break;
+ }
+
+ if (null !== $row['bit_null']) {
+ debug_zval_dump($row);
+ printf("[014 - %d] Expecting null got %s/%s\n", $bits, gettype($row['bit_value']), $row['bit_value']);
+ break;
+ }
+
+ }
+
+ mysqli_stmt_close($stmt_ins);
+ mysqli_stmt_close($stmt_sel);
+ }
+
+ mysqli_close($link_ins);
+ mysqli_close($link_sel);
+ print "done!";
+?>
+--EXPECTF--
+done!
+--UEXPECTF--
+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
index 0000000000..ba88686971
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_format.phpt
@@ -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_bind_result_references.phpt b/ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt
new file mode 100644
index 0000000000..6285cf31de
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_bind_result_references.phpt
@@ -0,0 +1,378 @@
+--TEST--
+mysqli_stmt_bind_result() - playing with references
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1"))
+ printf("[001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+
+ print "plain vanilla...\n";
+ unset($id); unset($label);
+ $id = $label = null;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[002] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($label);
+
+
+ print "reference, one level...\n";
+ unset($id); unset($id_ref); unset($label); unset($label_ref);
+ $id = null;
+ $id_ref = &$id;
+ $label = null;
+ $label_ref = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref, $label_ref)))
+ printf("[004] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref);
+ var_dump($label);
+
+
+ print "reference, two levels...\n";
+ unset($id); unset($id_ref); unset($id_ref_ref); unset($label); unset($label_ref); unset($label_ref_ref);
+ $id = null;
+ $id_ref = &$id;
+ $id_ref_ref = &$id_ref;
+ $label = null;
+ $label_ref = &$label;
+ $label_ref_ref = &$label_ref;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref_ref, $label_ref_ref)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref_ref);
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref_ref);
+ var_dump($label_ref);
+ var_dump($label);
+
+ print "reference, \$GLOBALS...\n";
+ unset($id); unset($id_ref); unset($label); unset($label_ref);
+ $id = 100;
+ $id_ref = &$GLOBALS['id'];
+ $label = null;
+ $label_ref = &$GLOBALS['label'];
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref, $label_ref)))
+ printf("[008] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref);
+ var_dump($label);
+
+ print "reference, same target...\n";
+ $id = null;
+ $label = &$id;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[010] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($label);
+
+ print "reference, simple object...\n";
+ unset($obj);
+ $obj = new stdClass();
+ $obj->id = null;
+ $obj->label = null;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $obj->id, $obj->label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($obj->id);
+ var_dump($obj->label);
+
+
+ print "reference, simple object w reference...\n";
+ unset($id); unset($label); unset($obj);
+ $obj = new stdClass();
+ $obj->id = null;
+ $obj->label = null;
+ $id = &$obj->id;
+ $label = &$obj->label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($obj->id);
+ var_dump($obj->label);
+
+ print "reference, simple object w reference, change after bind...\n";
+ unset($id); unset($label); unset($obj);
+ $obj = new stdClass();
+ $obj->id = null;
+ $obj->label = null;
+ $id = &$obj->id;
+ $label = &$obj->label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $label = &$obj->id;
+ $id = null;
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($obj->id);
+ var_dump($id);
+ var_dump($obj->label);
+ var_dump($label);
+
+ print "reference, one level, change after bind...\n";
+ unset($id); unset($label); unset($id_ref); unset($label_ref);
+ $id = null;
+ $id_ref = &$id;
+ $label = null;
+ $label_ref = &$label;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id_ref, $label_ref)))
+ printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $id_ref = 1;
+ $label_ref = 1;
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id_ref);
+ var_dump($id);
+ var_dump($label_ref);
+ var_dump($label);
+
+ print "reference, circle...\n";
+ unset($id); unset($label_a); unset($label_b);
+ $id = null;
+ $label_a = &$label_b;
+ $label_b = &$label_a;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label_a)))
+ printf("[016] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($label_a);
+ var_dump($label_b);
+
+ print "reference, object, forward declaration...\n";
+ unset($bar); unset($id); unset($label_ref);
+ class foo {
+ public $foo;
+ public function foo() {
+ $this->foo = &$this->bar;
+ }
+ }
+ class bar extends foo {
+ public $bar = null;
+ }
+ $bar = new bar();
+ $id = null;
+ $label_ref = &$bar->bar;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label_ref)))
+ printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ var_dump($bar);
+ var_dump($label_ref);
+
+ print "references, object, private...\n";
+ unset($bar); unset($id); unset($label);
+ class mega_bar extends bar {
+ private $id;
+ public $id_ref;
+ public function mega_bar() {
+ $this->foo();
+ $this->id_ref = &$this->id;
+ }
+ }
+ $bar = new mega_bar();
+ $id = &$bar->id_ref;
+ $label = &$bar->foo;
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[020] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[021] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ var_dump($id);
+ var_dump($label);
+ var_dump($bar);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+plain vanilla...
+int(1)
+string(1) "a"
+reference, one level...
+int(1)
+int(1)
+string(1) "a"
+string(1) "a"
+reference, two levels...
+int(1)
+int(1)
+int(1)
+string(1) "a"
+string(1) "a"
+string(1) "a"
+reference, $GLOBALS...
+int(1)
+int(1)
+string(1) "a"
+string(1) "a"
+reference, same target...
+string(1) "a"
+string(1) "a"
+reference, simple object...
+int(1)
+string(1) "a"
+reference, simple object w reference...
+int(1)
+string(1) "a"
+reference, simple object w reference, change after bind...
+int(1)
+int(1)
+string(1) "a"
+int(1)
+reference, one level, change after bind...
+int(1)
+int(1)
+string(1) "a"
+string(1) "a"
+reference, circle...
+int(1)
+string(1) "a"
+string(1) "a"
+reference, object, forward declaration...
+int(1)
+object(bar)#%d (2) {
+ ["bar"]=>
+ &string(1) "a"
+ ["foo"]=>
+ &string(1) "a"
+}
+string(1) "a"
+references, object, private...
+int(1)
+string(1) "a"
+object(mega_bar)#5 (4) {
+ [%s]=>
+ &int(1)
+ ["id_ref"]=>
+ &int(1)
+ ["bar"]=>
+ &string(1) "a"
+ ["foo"]=>
+ &string(1) "a"
+}
+done!
+--UEXPECTF--
+plain vanilla...
+int(1)
+unicode(1) "a"
+reference, one level...
+int(1)
+int(1)
+unicode(1) "a"
+unicode(1) "a"
+reference, two levels...
+int(1)
+int(1)
+int(1)
+unicode(1) "a"
+unicode(1) "a"
+unicode(1) "a"
+reference, $GLOBALS...
+int(1)
+int(1)
+unicode(1) "a"
+unicode(1) "a"
+reference, same target...
+unicode(1) "a"
+unicode(1) "a"
+reference, simple object...
+int(1)
+unicode(1) "a"
+reference, simple object w reference...
+int(1)
+unicode(1) "a"
+reference, simple object w reference, change after bind...
+int(1)
+int(1)
+unicode(1) "a"
+int(1)
+reference, one level, change after bind...
+int(1)
+int(1)
+unicode(1) "a"
+unicode(1) "a"
+reference, circle...
+int(1)
+unicode(1) "a"
+unicode(1) "a"
+reference, object, forward declaration...
+int(1)
+object(bar)#%d (2) {
+ [u"bar"]=>
+ &unicode(1) "a"
+ [u"foo"]=>
+ &unicode(1) "a"
+}
+unicode(1) "a"
+references, object, private...
+int(1)
+unicode(1) "a"
+object(mega_bar)#5 (4) {
+ [u"id":u"mega_bar":private]=>
+ &int(1)
+ [u"id_ref"]=>
+ &int(1)
+ [u"bar"]=>
+ &unicode(1) "a"
+ [u"foo"]=>
+ &unicode(1) "a"
+}
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_close.phpt b/ext/mysqli/tests/mysqli_stmt_close.phpt
new file mode 100644
index 0000000000..dbe86805ae
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_close.phpt
@@ -0,0 +1,87 @@
+--TEST--
+mysqli_stmt_close()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_close()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_close($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // Yes, amazing, eh? AFAIK a work around of a constructor bug...
+ if (!is_null($tmp = mysqli_stmt_close($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_close($stmt)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = mysqli_stmt_close($stmt)))
+ printf("[007] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "is", $id, $label))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 100; $label = 'z';
+ if (!mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true !== ($tmp = mysqli_stmt_close($stmt)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ require('table.inc');
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test"))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[015] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt) || !mysqli_stmt_fetch($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true !== ($tmp = mysqli_stmt_close($stmt)))
+ printf("[017] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_close(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_close(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_data_seek.phpt b/ext/mysqli/tests/mysqli_stmt_data_seek.phpt
new file mode 100644
index 0000000000..daabed8cd2
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_data_seek.phpt
@@ -0,0 +1,95 @@
+--TEST--
+mysqli_stmt_data_seek()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_data_seek()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_data_seek($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, 1)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+
+ $id = null;
+ if (!mysqli_stmt_bind_result($stmt, $id))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, 2)))
+ printf("[009] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, 0)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ if (!is_null($tmp = mysqli_stmt_data_seek($stmt, mysqli_stmt_num_rows($stmt) + 100)))
+ printf("[013] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_fetch($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ if (false !== ($tmp = mysqli_stmt_data_seek($stmt, -1)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_fetch($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_data_seek($stmt, 0)))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_data_seek(): invalid object or resource mysqli_stmt
+ in %s on line %d
+int(3)
+int(1)
+int(1)
+
+Warning: mysqli_stmt_data_seek(): Offset must be positive in %s on line %d
+int(1)
+
+Warning: mysqli_stmt_data_seek(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_errno.phpt b/ext/mysqli/tests/mysqli_stmt_errno.phpt
new file mode 100644
index 0000000000..16f9baaa5c
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_errno.phpt
@@ -0,0 +1,64 @@
+--TEST--
+mysqli_stmt_errno()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_errno()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_errno($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // properly initialized?
+ if (0 !== ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[004] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, "SELECT i_do_not_exist_believe_me FROM test ORDER BY id"))
+ printf("[005] Statement should have failed!\n");
+
+ // set after error server?
+ if (0 === ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[006] Expecting int/any non zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id"))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // reset after error & success
+ if (0 != ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[008] Expecting zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true === ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ // set after client error
+ if (0 === ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[010] Execting int/any non zero, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_errno($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_errno(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_error.phpt b/ext/mysqli/tests/mysqli_stmt_error.phpt
new file mode 100644
index 0000000000..2c46e142b8
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_error.phpt
@@ -0,0 +1,64 @@
+--TEST--
+mysqli_stmt_error()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_error()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_error($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // properly initialized?
+ if ('' !== ($tmp = mysqli_stmt_error($stmt)))
+ printf("[004] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, "SELECT i_do_not_exist_believe_me FROM test ORDER BY id"))
+ printf("[005] Statement should have failed!\n");
+
+ // set after error server?
+ if ('' === ($tmp = mysqli_stmt_error($stmt)))
+ printf("[006] Expecting string/any non empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id"))
+ printf("[007] [%d] %s\n", mysqli_stmt_error($stmt), mysqli_stmt_error($stmt));
+
+ // reset after error & success
+ if ('' !== ($tmp = mysqli_stmt_error($stmt)))
+ printf("[008] Expecting empty string, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (true === ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ // set after client error
+ if ('' === ($tmp = mysqli_stmt_error($stmt)))
+ printf("[010] Execting string/any non empty, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_error($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_error(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_execute.phpt b/ext/mysqli/tests/mysqli_stmt_execute.phpt
new file mode 100644
index 0000000000..3106e8e38f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_execute.phpt
@@ -0,0 +1,81 @@
+--TEST--
+mysqli_stmt_execute()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_execute()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_execute($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, "SELECT i_do_not_exist_believe_me FROM test ORDER BY id"))
+ printf("[005] Statement should have failed!\n");
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test ORDER BY id LIMIT 1"))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[008] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[009] [%d] %s\n", mysqli_stmt_execute($stmt), mysqli_stmt_execute($stmt));
+
+ // no input variables bound
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[010] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ $id = 100;
+ $label = "z";
+ if (!mysqli_stmt_bind_param($stmt, "is", $id, $label))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_kill($link, mysqli_thread_id($link));
+
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[014] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_execute(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_execute(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_execute(): Couldn't fetch mysqli_stmt in %s on line %d
+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
index 0000000000..f6b7444cba
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_execute_stored_proc.phpt
@@ -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
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch.phpt b/ext/mysqli/tests/mysqli_stmt_fetch.phpt
new file mode 100644
index 0000000000..ac0c07c940
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch.phpt
@@ -0,0 +1,94 @@
+--TEST--
+mysqli_stmt_fetch()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--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";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_fetch()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_fetch($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_fetch($stmt))) && (false !== $tmp))
+ printf("[006] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[008] NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = NULL;
+ $label = NULL;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[012] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[013] Expecting boolean/true, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_kill($link, mysqli_thread_id($link)))
+ printf("[014] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[015] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[016] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_fetch()))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+[014] [%d] Commands out of sync; you can't run this command now
+
+Warning: mysqli_stmt_fetch(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt b/ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt
new file mode 100644
index 0000000000..0846599b3e
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch_bit.phpt
@@ -0,0 +1,71 @@
+--TEST--
+Fetching BIT column values using the PS API
+--SKIPIF--
+<?php
+ require_once('skipif.inc');
+ require_once('skipifemb.inc');
+ require_once('skipifconnectfailure.inc');
+ require_once('connect.inc');
+ require_once('table.inc');
+ if (mysqli_get_server_version($link) < 50003)
+ // b'001' syntax not supported before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+ if (!$IS_MYSQLND && (mysqli_get_client_version() < 50003))
+ // better don't trust libmysql before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ if (!$link = 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);
+
+ for ($bits = 1; $bits < 64; $bits++) {
+ $max_value = pow(2, $bits) - 1;
+ $tests = 0;
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, $sql = sprintf('CREATE TABLE test(id INT, label BIT(%d)) ENGINE="%s"', $bits, $engine)))
+ printf("[002 - %d] [%d] %s\n",$bits, mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ while ($tests < min($max_value, 20)) {
+ $tests++;
+ $value = mt_rand(0, $max_value);
+ $sql = sprintf("INSERT INTO test(id, label) VALUES (%d, b'%s')", $value, decbin($value));
+
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $_label0 = $label = null;
+ $sql = sprintf("SELECT id, label + 0 AS _label0, label FROM test WHERE id = %d", $value);
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt) ||
+ !mysqli_stmt_bind_result($stmt, $id, $_label0, $label))
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[006 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (($id !== $_label0) || ($value !== $_label0)) {
+ printf("[007 - %d] Insert of %d in BIT(%d) column might have failed. MySQL reports odd values, id = %s, _label0 = %s, label = %s.\n", $bits, $value, $bits, $id, $_label0, $label);
+ }
+ if ($value != $label) {
+ printf("[008 - %d] Wrong values, (original) value = %s, id = %s, label + 0 AS label0 = %s, label = %s\n",
+ $bits, $value, $id, $_label0, $label);
+ }
+ }
+
+ mysqli_stmt_close($stmt);
+
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt b/ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt
new file mode 100644
index 0000000000..d858c94da0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_fetch_fields_win32_unicode.phpt
@@ -0,0 +1,52 @@
+--TEST--
+mysqli_stmt_fetch_fields() unicode, win32
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ require('table.inc');
+
+ $bind_res = $id = null;
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test") ||
+ !mysqli_stmt_execute($stmt) ||
+ !($result = mysqli_stmt_result_metadata($stmt)) ||
+ !mysqli_stmt_bind_result($stmt, $id, $bind_res) ||
+ !($fields = mysqli_fetch_fields($result))) {
+ printf("FAIL 1\n");
+ }
+ while (mysqli_stmt_fetch($stmt)) {
+ ;
+ }
+ mysqli_free_result($result);
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test") ||
+ !mysqli_stmt_execute($stmt) ||
+ !($result = mysqli_stmt_result_metadata($stmt)) ||
+ !mysqli_stmt_bind_result($stmt, $id, $bind_res)) {
+ printf("FAIL 2\n");
+ }
+ print "OK: 1\n";
+ if (!($fields = mysqli_fetch_fields($result)))
+ printf("Aua 3\n");
+ print "OK: 2\n";
+ while (mysqli_stmt_fetch($stmt)) {
+ ;
+ }
+ mysqli_free_result($result);
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+OK: 1
+OK: 2
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_field_count.phpt b/ext/mysqli/tests/mysqli_stmt_field_count.phpt
new file mode 100644
index 0000000000..c7f46a7bc1
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_field_count.phpt
@@ -0,0 +1,94 @@
+--TEST--
+mysqli_stmt_field_counts()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_field_count()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_field_count($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (!is_null($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_stmt_prepare($stmt, ''))
+ printf("[004] Prepare should fail for an empty statement\n");
+ if (!is_null($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT 1'))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (1 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[007] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT 1, 2'))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (2 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[009] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test'))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (2 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[011] Expecting int/2, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT label FROM test') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (1 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[013] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ $label = null;
+ if (mysqli_stmt_bind_param($stmt, "s", $label))
+ printf("[014] expected error - got ok\n");
+ while (mysqli_stmt_fetch($stmt))
+ if (1 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[015] Expecting int/1, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id) VALUES (100)'))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ if (0 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[017] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'UPDATE test SET label = "z" WHERE id = 1') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (0 !== ($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[019] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (mysqli_stmt_prepare($stmt, 'SELECT id FROM test'))
+ printf("[020] Prepare should fail, statement has been closed\n");
+ if (!is_null($tmp = mysqli_stmt_field_count($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_field_count(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_field_count(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_prepare(): Couldn't fetch mysqli_stmt in %s on line %d
+
+Warning: mysqli_stmt_field_count(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_free_result.phpt b/ext/mysqli/tests/mysqli_stmt_free_result.phpt
new file mode 100644
index 0000000000..db9defc637
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_free_result.phpt
@@ -0,0 +1,82 @@
+--TEST--
+mysqli_stmt_free_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--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";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_free_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_free_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[006] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[008] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[009] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id"))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[014] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_free_result($stmt)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_free_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_free_result(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result.phpt b/ext/mysqli/tests/mysqli_stmt_get_result.phpt
new file mode 100644
index 0000000000..3c586508cf
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result.phpt
@@ -0,0 +1,209 @@
+--TEST--
+mysqli_stmt_get_result()
+--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";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_get_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_get_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_get_result($stmt))) && (false !== $tmp))
+ printf("[006] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_store_result($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (is_object($tmp = mysqli_stmt_store_result($stmt)))
+ printf("[009] non-object, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[011] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ // FIXME - different versions return different values ?!
+ if ((NULL !== ($tmp = mysqli_stmt_get_result($stmt))) && (false !== $tmp))
+ printf("[013] Expecting NULL or boolean/false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[016] NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_free_result($tmp);
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[019] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[020] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[023] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[024] Expecting object, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[025] false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label))) {
+ printf("[026] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[027] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
+ printf("[028] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+ }
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[029] false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[032] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 2"))
+ printf("[033] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[034] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = NULL;
+ $label = NULL;
+ if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label)))
+ printf("[035] Expecting boolean/true, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ if (!is_object($tmp = $result = mysqli_stmt_get_result($stmt)))
+ printf("[036] Expecting array, got %s/%s, [%d] %s\n",
+ gettype($tmp), var_export($tmp, 1),
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[037] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ printf("[038] [%d] [%s]\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ printf("[039] [%d] [%s]\n", mysqli_errno($link), mysqli_error($link));
+ while ($row = mysqli_fetch_assoc($result)) {
+ var_dump($row);
+ }
+ mysqli_free_result($result);
+
+ if (!mysqli_kill($link, mysqli_thread_id($link)))
+ printf("[040] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_stmt_get_result($stmt)))
+ printf("[041] Expecting false, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_fetch($stmt)))
+ printf("[042] Expecting NULL, got %s/%s\n", gettype($tmp), var_export($tmp, 1));
+
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_get_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+[038] [2014] [Commands out of sync; you can't run this command now]
+[039] [0] []
+array(2) {
+ ["id"]=>
+ int(1)
+ ["label"]=>
+ %s(1) "a"
+}
+array(2) {
+ ["id"]=>
+ int(2)
+ ["label"]=>
+ %s(1) "b"
+}
+
+Warning: mysqli_stmt_fetch(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
+--UEXPECTF--
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_fetch(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_get_result(): invalid object or resource mysqli_stmt
+ in %s on line %d
+[038] [2014] [Commands out of sync; you can't run this command now]
+[039] [0] []
+array(2) {
+ [%s"id"]=>
+ int(1)
+ [%s"label"]=>
+ %s(1) "a"
+}
+array(2) {
+ [%s"id"]=>
+ int(2)
+ [%s"label"]=>
+ %s(1) "b"
+}
+
+Warning: mysqli_stmt_fetch(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result2.phpt b/ext/mysqli/tests/mysqli_stmt_get_result2.phpt
new file mode 100644
index 0000000000..4ba8e24544
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result2.phpt
@@ -0,0 +1,191 @@
+--TEST--
+mysqli_stmt_get_result()
+--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";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_get_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_get_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_null($tmp = @mysqli_stmt_get_result($stmt, "foo")))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 1"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[007] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ while ($row = mysqli_fetch_assoc($res))
+ var_dump($row);
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ if (false !== ($res = mysqli_stmt_get_result($stmt))) {
+ printf("[008] boolean/false got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ mysqli_stmt_execute($stmt);
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[009] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ while ($row = mysqli_fetch_assoc($res))
+ var_dump($row);
+ var_dump(mysqli_fetch_assoc($res));
+ mysqli_free_result($res);
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($res = mysqli_stmt_get_result($stmt))) {
+ printf("[013] boolean/false got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[015] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[018] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[019] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ $id = $label = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[020] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $row = mysqli_fetch_assoc($res);
+ if (NULL !== $id || NULL !== $label)
+ printf("[021] Bound variables should not have been set\n");
+ mysqli_free_result($res);
+
+ mysqli_stmt_close($stmt);
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 2") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[022] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[023] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ if (!in_array($res->type, array(MYSQLI_STORE_RESULT, MYSQLI_USE_RESULT))) {
+ printf("[024] Unknown result set type %s\n", $res->type);
+ }
+ if ($res->type !== MYSQLI_STORE_RESULT)
+ printf("[025] Expecting int/%d got %s/%s", MYSQLI_STORE_RESULT, gettype($res->type), $res->type);
+
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ if (NULL !== ($res = mysqli_stmt_get_result($stmt))) {
+ printf("[022] Expecting NULL got %s/%s\n",
+ gettype($res), $res);
+ }
+
+ print "done!";
+?>
+--EXPECTF--
+array(2) {
+ ["id"]=>
+ int(1)
+ ["label"]=>
+ string(1) "a"
+}
+NULL
+array(2) {
+ ["id"]=>
+ int(1)
+ ["label"]=>
+ string(1) "a"
+}
+NULL
+[017] [2014] Commands out of sync; you can't run this command now
+
+Warning: mysqli_stmt_get_result(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
+--UEXPECTF--
+array(2) {
+ [u"id"]=>
+ int(1)
+ [u"label"]=>
+ unicode(1) "a"
+}
+NULL
+array(2) {
+ [u"id"]=>
+ int(1)
+ [u"label"]=>
+ unicode(1) "a"
+}
+NULL
+[017] [2014] Commands out of sync; you can't run this command now
+
+Warning: mysqli_stmt_get_result(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt
new file mode 100644
index 0000000000..27ca389093
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_bit.phpt
@@ -0,0 +1,129 @@
+--TEST--
+Fetching BIT column values using the PS API
+--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");
+
+ require_once('connect.inc');
+ require_once('table.inc');
+ if (mysqli_get_server_version($link) < 50003)
+ // b'001' syntax not supported before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+ if (!$IS_MYSQLND && (mysqli_get_client_version() < 50003))
+ // better don't trust libmysql before 5.0.3
+ die("skip Syntax used for test not supported with MySQL Server before 5.0.3");
+?>
+--FILE--
+<?php
+ require('connect.inc');
+
+ function dec32bin($dec, $bits) {
+
+ $maxval = pow(2, $bits);
+ $bin = '';
+ for ($bitval = $maxval; $bitval >= 1; $bitval = $bitval / 2) {
+ if (($dec / $bitval) >= 1) {
+ $bin .= '1';
+ $dec -= $bitval;
+ } else {
+ $bin .= '0';
+ }
+ }
+ return $bin;
+ }
+
+ if (!$link = 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);
+
+ for ($bits = 1; $bits <= 46; $bits++) {
+ if (1 == $bits)
+ $max_value = 1;
+ else
+ $max_value = pow(2, $bits) - 1;
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test") ||
+ !mysqli_query($link, $sql = sprintf('CREATE TABLE test(id BIGINT UNSIGNED, bit_value BIT(%d) NOT NULL, bit_null BIT(%d) DEFAULT NULL) ENGINE="%s"', $bits, $bits, $engine)))
+ printf("[002 - %d] [%d] %s\n",$bits, mysqli_errno($link), mysqli_error($link));
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+
+ $tests = 0;
+ $rand_max = mt_getrandmax();
+ while ($tests < 10) {
+
+ $tests++;
+ if (1 == $tests)
+ $value = 0;
+ else if (2 == $tests)
+ $value = $max_value;
+ else {
+ if ($max_value > $rand_max) {
+ $max_loops = floor($max_value/$rand_max);
+ $num_loops = mt_rand(1, $max_loops);
+ $value = 0;
+ for ($i = 0; $i < $num_loops; $i++)
+ $value += mt_rand(0, $rand_max);
+ } else {
+ $value = mt_rand(0, $max_value);
+ }
+ }
+
+ $bin = ($bits < 32) ? decbin($value) : dec32bin($value, $bits);
+ $sql = sprintf("INSERT INTO test(id, bit_value) VALUES (%s, b'%s')", $value, $bin);
+ for ($i = 0; ($i < strlen($bin)) && ($bin[$i] == '0'); $i++)
+ ;
+ $bin2 = substr($bin, $i, strlen($bin));
+
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[004 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $sql = sprintf("SELECT bin(bit_value) AS _bin, id, bit_value, bit_null FROM test WHERE id = %s", $value);
+ if (!mysqli_stmt_prepare($stmt, $sql) ||
+ !mysqli_stmt_execute($stmt))
+ printf("[005 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_stmt_get_result($stmt))
+ printf("[006 - %d] [%d] %s\n", $bits, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007 - %d] [%d] %s\n", $bits, mysqli_errno($link), mysqli_error($link));
+ mysqli_free_result($res);
+
+ if (($value != $row['id']) || (($bin != $row['_bin']) && ($bin2 != $row['_bin']))) {
+ debug_zval_dump($row);
+ printf("[008 - %d] Insert of %s in BIT(%d) column might have failed. id = %s, bin = %s (%s/%s)\n",
+ $bits, $value, $bits, $row['id'], $row['_bin'], $bin, $bin2);
+ break;
+ }
+ if ($value != $row['bit_value']) {
+ debug_zval_dump($row);
+ printf("%10s %64s\n%10s %64s\n", '_bin', $row['_bin'], 'insert', $bin);
+ printf("[009 - %d] Expecting %s got %s\n", $bits, $value, $row['bit_value']);
+ break;
+ }
+
+ if (null !== $row['bit_null']) {
+ debug_zval_dump($row);
+ printf("[010 - %d] Expecting null got %s/%s\n", $bits, gettype($row['bit_value']), $row['bit_value']);
+ break;
+ }
+
+ }
+
+ mysqli_stmt_close($stmt);
+
+ }
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt
new file mode 100644
index 0000000000..6a7131b926
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_field_count.phpt
@@ -0,0 +1,47 @@
+--TEST--
+mysqli_stmt_get_result() - meta data, field_count()
+--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
+ 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_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3"))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[004] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[005] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ printf("%s %s\n",
+ $res_meta->field_count,
+ $res->field_count);
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+2 2
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt
new file mode 100644
index 0000000000..afaa5765d9
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_metadata.phpt
@@ -0,0 +1,260 @@
+--TEST--
+mysqli_stmt_get_result() - meta data
+--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
+ 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_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3"))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[004] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[005] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ var_dump(mysqli_fetch_assoc($res));
+ var_dump(mysqli_fetch_assoc($res_meta));
+
+ mysqli_free_result($res);
+ mysqli_free_result($res_meta);
+ mysqli_stmt_close($stmt);
+
+ // !mysqli_stmt_prepare($stmt, "SELECT id, label, id + 1 as _id, concat(label, '_') _label FROM test as _test ORDER BY id ASC LIMIT 3") ||
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id , label, id + 1 AS _id, label AS _label, null AS _null, CONCAT(label, '_') _label_concat FROM test _test ORDER BY id ASC LIMIT 3") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[007] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[008] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (($tmp1 = mysqli_num_fields($res)) !== ($tmp2 = mysqli_num_fields($res_meta))) {
+ printf("[009] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+ }
+
+ /*
+ if (($tmp1 = mysqli_field_count($link)) !== ($tmp2 = $res->field_count()))
+ printf("[010] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+
+ if (($tmp1 = $res_meta->field_count()) !== $tmp2)
+ printf("[011] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+ */
+
+ if (($tmp1 = mysqli_field_tell($res)) !== ($tmp2 = $res_meta->current_field))
+ printf("[012] %s/%s !== %s/%s\n", gettype($tmp1), $tmp1, gettype($tmp2), $tmp2);
+
+ if (0 !== $tmp1)
+ printf("[013] Expecting int/0 got %s/%s\n", gettype($tmp1), $tmp1);
+
+ $fields = array();
+ while ($info = $res->fetch_field())
+ $fields['res'][] = $info;
+ var_dump($info);
+ while ($info = $res_meta->fetch_field())
+ $fields['meta'][] = $info;
+ var_dump($info);
+ $fields['all_res'] = $res->fetch_fields();
+ $fields['all_meta'] = $res_meta->fetch_fields();
+
+ if (count($fields['res']) != count($fields['meta'])) {
+ printf("[014] stmt_get_result indicates %d fields, stmt_result_metadata indicates %d fields\n",
+ count($fields['res']),
+ count($fields['meta']));
+ }
+
+ foreach ($fields['res'] as $k => $info) {
+ printf("%s\n", $info->name);
+ if ($info->name !== $fields['meta'][$k]->name)
+ printf("[015 - %d] Expecting name %s/%s got %s/%s\n",
+ $k, gettype($info->name), $info->name, gettype($fields['meta'][$k]->name), $fields['meta'][$k]->name);
+
+ if ($info->orgname !== $fields['meta'][$k]->orgname)
+ printf("[016 - %d] Expecting orgname %s/%s got %s/%s\n",
+ $k, gettype($info->orgname), $info->orgname, gettype($fields['meta'][$k]->orgname), $fields['meta'][$k]->orgname);
+
+ if ($info->table !== $fields['meta'][$k]->table)
+ printf("[017 - %d] Expecting table %s/%s got %s/%s\n",
+ $k, gettype($info->table), $info->table, gettype($fields['meta'][$k]->table), $fields['meta'][$k]->table);
+
+ if ($info->orgtable !== $fields['meta'][$k]->orgtable)
+ printf("[018 - %d] Expecting orgtable %s/%s got %s/%s\n",
+ $k, gettype($info->orgtable), $info->orgtable, gettype($fields['meta'][$k]->orgtable), $fields['meta'][$k]->orgtable);
+
+ if ($info->def !== $fields['meta'][$k]->def)
+ printf("[019 - %d] Expecting def %s/%s got %s/%s\n",
+ $k, gettype($info->def), $info->def, gettype($fields['meta'][$k]->def), $fields['meta'][$k]->def);
+/*
+ if ($info->max_length !== $fields['meta'][$k]->max_length)
+ printf("[020 - %d] Expecting max_length %s/%s got %s/%s\n",
+ $k, gettype($info->max_length), $info->max_length, gettype($fields['meta'][$k]->max_length), $fields['meta'][$k]->max_length);
+*/
+ if ($info->length !== $fields['meta'][$k]->length)
+ printf("[021 - %d] Expecting length %s/%s got %s/%s\n",
+ $k, gettype($info->length), $info->length, gettype($fields['meta'][$k]->length), $fields['meta'][$k]->length);
+
+ if ($info->charsetnr !== $fields['meta'][$k]->charsetnr)
+ printf("[022 - %d] Expecting charsetnr %s/%s got %s/%s\n",
+ $k, gettype($info->charsetnr), $info->charsetnr, gettype($fields['meta'][$k]->charsetnr), $fields['meta'][$k]->charsetnr);
+
+ if ($info->flags !== $fields['meta'][$k]->flags)
+ printf("[023 - %d] Expecting flags %s/%s got %s/%s\n",
+ $k, gettype($info->flags), $info->flags, gettype($fields['meta'][$k]->flags), $fields['meta'][$k]->flags);
+
+ if ($info->type !== $fields['meta'][$k]->type)
+ printf("[024 - %d] Expecting type %s/%s got %s/%s\n",
+ $k, gettype($info->type), $info->type, gettype($fields['meta'][$k]->type), $fields['meta'][$k]->type);
+
+ if ($info->decimals !== $fields['meta'][$k]->decimals)
+ printf("[025 - %d] Expecting decimals %s/%s got %s/%s\n",
+ $k, getdecimals($info->decimals), $info->decimals, getdecimals($fields['meta'][$k]->decimals), $fields['meta'][$k]->decimals);
+
+ /* Make them equal for the check */
+ $tmp = $fields['all_res'][$k]->max_length;
+ $fields['all_res'][$k]->max_length = $fields['all_meta'][$k]->max_length;
+
+ if ($fields['all_res'][$k] != $fields['all_meta'][$k]) {
+ printf("[026 - %d] fetch_fields() seems to have returned different data, dumping\n", $k);
+ var_dump($fields['all_res'][$k]);
+ var_dump($fields['all_meta'][$k]);
+ }
+ $fields['all_res'][$k]->max_length = $tmp;
+ }
+
+ $num = count($fields['res']);
+ for ($i = 0; $i < 100; $i++) {
+ $pos = mt_rand(-1, $num + 1);
+ if ($pos >= 0 && $pos < $num) {
+ if (true !== mysqli_field_seek($res, $pos))
+ printf("[027] field_seek(res) failed\n");
+ if (true !== $res_meta->field_seek($pos))
+ printf("[028] field_seek(res__meta) failed\n");
+
+ $tmp1 = $res->fetch_field();
+ $tmp2 = mysqli_fetch_field($res_meta);
+ $tmp2->max_length = $tmp1->max_length;
+ if ($tmp1 != $tmp2) {
+ printf("[029] Field info differs, dumping data\n");
+ var_dump($tmp1);
+ var_dump($tmp2);
+ }
+
+ if ($tmp1 != $fields['res'][$pos]) {
+ printf("[030] Field info differs, dumping data\n");
+ var_dump($tmp1);
+ var_dump($fields['res'][$pos]);
+ }
+
+ $pos++;
+ if ($pos !== ($tmp = mysqli_field_tell($res)))
+ printf("[031] Expecting %s/%s got %s/%s\n",
+ gettype($pos), $pos, gettype($tmp), $tmp);
+
+ if ($pos !== ($tmp = mysqli_field_tell($res_meta)))
+ printf("[032] Expecting %s/%s got %s/%s\n",
+ gettype($pos), $pos, gettype($tmp), $tmp);
+ } else {
+
+ if (false !== @mysqli_field_seek($res, $pos))
+ printf("[033] field_seek(%d) did not fail\n", $pos);
+ if (false !== @mysqli_field_seek($res_meta, $pos))
+ printf("[034] field_seek(%d) did not fail\n", $pos);
+ }
+ }
+
+ $res->free_result();
+ mysqli_free_result($res_meta);
+
+ var_dump(mysqli_fetch_field($res));
+
+ mysqli_stmt_close($stmt);
+
+ var_dump(mysqli_fetch_field($res));
+
+ mysqli_close($link);
+
+ var_dump(mysqli_fetch_field($res));
+
+ print "done!";
+?>
+--EXPECTF--
+array(2) {
+ ["id"]=>
+ int(1)
+ ["label"]=>
+ string(1) "a"
+}
+NULL
+bool(false)
+bool(false)
+id
+label
+_id
+_label
+_null
+_label_concat
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done!
+--UEXPECTF--
+array(2) {
+ [u"id"]=>
+ int(1)
+ [u"label"]=>
+ unicode(1) "a"
+}
+NULL
+bool(false)
+bool(false)
+id
+label
+_id
+_label
+_null
+_label_concat
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+
+Warning: mysqli_fetch_field(): Couldn't fetch mysqli_result in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt
new file mode 100644
index 0000000000..12489cef5d
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_metadata_fetch_field.phpt
@@ -0,0 +1,237 @@
+--TEST--
+mysqli_stmt_get_result() - meta data, field info
+--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
+ include "connect.inc";
+ require('table.inc');
+
+ if (!($stmt = mysqli_stmt_init($link)) ||
+ !mysqli_stmt_prepare($stmt, "SELECT id, label, id + 1 as _id, concat(label, '_') ___label FROM test ORDER BY id ASC LIMIT 3") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[007] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!is_object($res_meta = mysqli_stmt_result_metadata($stmt)) ||
+ 'mysqli_result' != get_class($res_meta)) {
+ printf("[008] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ $fields = array();
+ while ($info = $res->fetch_field()) {
+ var_dump($info);
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+object(stdClass)#%d (11) {
+ ["name"]=>
+ string(2) "id"
+ ["orgname"]=>
+ string(2) "id"
+ ["table"]=>
+ string(4) "test"
+ ["orgtable"]=>
+ string(4) "test"
+ ["def"]=>
+ string(0) ""
+ ["max_length"]=>
+ int(0)
+ ["length"]=>
+ int(11)
+ ["charsetnr"]=>
+ int(63)
+ ["flags"]=>
+ int(49155)
+ ["type"]=>
+ int(3)
+ ["decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (11) {
+ ["name"]=>
+ string(5) "label"
+ ["orgname"]=>
+ string(5) "label"
+ ["table"]=>
+ string(4) "test"
+ ["orgtable"]=>
+ string(4) "test"
+ ["def"]=>
+ string(0) ""
+ ["max_length"]=>
+ int(1)
+ ["length"]=>
+ int(1)
+ ["charsetnr"]=>
+ int(8)
+ ["flags"]=>
+ int(0)
+ ["type"]=>
+ int(254)
+ ["decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (11) {
+ ["name"]=>
+ string(3) "_id"
+ ["orgname"]=>
+ string(0) ""
+ ["table"]=>
+ string(0) ""
+ ["orgtable"]=>
+ string(0) ""
+ ["def"]=>
+ string(0) ""
+ ["max_length"]=>
+ int(0)
+ ["length"]=>
+ int(%d)
+ ["charsetnr"]=>
+ int(63)
+ ["flags"]=>
+ int(32897)
+ ["type"]=>
+ int(8)
+ ["decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (11) {
+ ["name"]=>
+ string(8) "___label"
+ ["orgname"]=>
+ string(0) ""
+ ["table"]=>
+ string(0) ""
+ ["orgtable"]=>
+ string(0) ""
+ ["def"]=>
+ string(0) ""
+ ["max_length"]=>
+ int(2)
+ ["length"]=>
+ int(2)
+ ["charsetnr"]=>
+ int(8)
+ ["flags"]=>
+ int(0)
+ ["type"]=>
+ int(253)
+ ["decimals"]=>
+ int(31)
+}
+done!
+--UEXPECTF--
+object(stdClass)#%d (11) {
+ [u"name"]=>
+ unicode(2) "id"
+ [u"orgname"]=>
+ unicode(2) "id"
+ [u"table"]=>
+ unicode(4) "test"
+ [u"orgtable"]=>
+ unicode(4) "test"
+ [u"def"]=>
+ unicode(0) ""
+ [u"max_length"]=>
+ int(0)
+ [u"length"]=>
+ int(11)
+ [u"charsetnr"]=>
+ int(63)
+ [u"flags"]=>
+ int(49155)
+ [u"type"]=>
+ int(3)
+ [u"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (11) {
+ [u"name"]=>
+ unicode(5) "label"
+ [u"orgname"]=>
+ unicode(5) "label"
+ [u"table"]=>
+ unicode(4) "test"
+ [u"orgtable"]=>
+ unicode(4) "test"
+ [u"def"]=>
+ unicode(0) ""
+ [u"max_length"]=>
+ int(1)
+ [u"length"]=>
+ int(3)
+ [u"charsetnr"]=>
+ int(33)
+ [u"flags"]=>
+ int(0)
+ [u"type"]=>
+ int(254)
+ [u"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (11) {
+ [u"name"]=>
+ unicode(3) "_id"
+ [u"orgname"]=>
+ unicode(0) ""
+ [u"table"]=>
+ unicode(0) ""
+ [u"orgtable"]=>
+ unicode(0) ""
+ [u"def"]=>
+ unicode(0) ""
+ [u"max_length"]=>
+ int(0)
+ [u"length"]=>
+ int(%d)
+ [u"charsetnr"]=>
+ int(63)
+ [u"flags"]=>
+ int(32897)
+ [u"type"]=>
+ int(8)
+ [u"decimals"]=>
+ int(0)
+}
+object(stdClass)#%d (11) {
+ [u"name"]=>
+ unicode(8) "___label"
+ [u"orgname"]=>
+ unicode(0) ""
+ [u"table"]=>
+ unicode(0) ""
+ [u"orgtable"]=>
+ unicode(0) ""
+ [u"def"]=>
+ unicode(0) ""
+ [u"max_length"]=>
+ int(2)
+ [u"length"]=>
+ int(6)
+ [u"charsetnr"]=>
+ int(33)
+ [u"flags"]=>
+ int(0)
+ [u"type"]=>
+ int(253)
+ [u"decimals"]=>
+ int(31)
+}
+done! \ No newline at end of file
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
index 0000000000..12e33f2209
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_non_select.phpt
@@ -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_seek.phpt b/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt
new file mode 100644
index 0000000000..54e4aeb609
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_seek.phpt
@@ -0,0 +1,126 @@
+--TEST--
+mysqli_stmt_get_result() - seeking
+--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
+ 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_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id ASC LIMIT 3"))
+ printf("[002] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[003] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($res = mysqli_stmt_get_result($stmt)) || 'mysqli_result' != get_class($res)) {
+ printf("[004] Expecting object/mysqli_result got %s/%s, [%d] %s\n",
+ gettype($res), $res, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (3 !== $res->num_rows)
+ printf("[005] Expecting 3 rows, got %s/%s rows\n", gettype($res->num_rows), $res->num_rows);
+
+ if (2 !== $res->field_count)
+ printf("[006] Expecting 2 fields, got %s/%s rows\n", gettype($res->field_count), $res->field_count);
+
+ if (0 !== $res->current_field)
+ printf("[006] Expecting offset 0, got %s/%s rows\n", gettype($res->current_field), $res->current_field);
+
+ for ($i = 2; $i > 0; $i--) {
+ if (!$res->data_seek($i))
+ printf("[007] Cannot seek to position %d, [%d] %s\n",
+ $i, mysqli_stmt_errno($stmt), $stmt->error);
+ $row = $res->fetch_array(MYSQLI_BOTH);
+ if (($row[0] !== $row['id']) || ($row[0] !== $i + 1)) {
+ printf("[008] Record looks wrong, dumping data\n");
+ var_dump($row);
+ } else {
+ unset($row[0]);
+ unset($row['id']);
+ }
+ if ($row[1] !== $row['label']) {
+ printf("[009] Record looks wrong, dumping data\n");
+ var_dump($row);
+ } else {
+ unset($row[1]);
+ unset($row['label']);
+ }
+ if (!empty($row)) {
+ printf("[010] Not empty, dumping unexpected data\n");
+ var_dump($row);
+ }
+ }
+
+ if (false !== ($tmp = $res->data_seek(-1)))
+ printf("[011] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $res->data_seek($res->num_rows + 1)))
+ printf("[012] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = $res->data_seek(PHP_INT_MAX + 1)))
+ printf("[013] Expecting boolean/false got %s/%s\n", gettype($tmp), $tmp);
+
+ for ($i = 0; $i < 100; $i++) {
+ /* intentionally out of range! */
+ $pos = mt_rand(-1, 4);
+ $tmp = mysqli_data_seek($res, $pos);
+ if (($pos >= 0 && $pos < 3)) {
+ if (true !== $tmp)
+ printf("[015] Expecting boolan/true got %s/%s\n", gettype($tmp), $tmp);
+ $row = $res->fetch_array(MYSQLI_NUM);
+ if ($row[0] !== $pos + 1)
+ printf("[016] Expecting id = %d for pos %d got %s/%s\n",
+ $pos + 1, $pos, gettype($row[0]), $row[0]);
+ } else {
+ if (false !== $tmp)
+ printf("[014] Expecting boolan/false got %s/%s\n", gettype($tmp), $tmp);
+ }
+ }
+
+ mysqli_stmt_close($stmt);
+
+ if (true !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[015] Expecting boolan/true got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_array($row = $res->fetch_array(MYSQLI_NUM)))
+ printf("[016] Expecting array got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_free_result($res);
+
+ if (NULL !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[017] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($row = $res->fetch_array(MYSQLI_NUM)))
+ printf("[018] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_data_seek($res, 0)))
+ printf("[019] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ if (NULL !== ($row = $res->fetch_array(MYSQLI_NUM)))
+ printf("[020] Expecting NULL got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+
+Warning: mysqli_data_seek(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: mysqli_result::fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: mysqli_data_seek(): Couldn't fetch mysqli_result in %s on line %d
+
+Warning: mysqli_result::fetch_array(): Couldn't fetch mysqli_result in %s on line %d
+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
index 0000000000..f70eea7c33
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_result_types.phpt
@@ -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/mysqli_stmt_get_warnings.phpt b/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
new file mode 100644
index 0000000000..9f8f824b95
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_get_warnings.phpt
@@ -0,0 +1,87 @@
+--TEST--
+mysqli_stmt_get_warnings() - TODO
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ require_once("connect.inc");
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_get_warnings()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_get_warnings($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "DROP TABLE IF EXISTS test") || !mysqli_stmt_execute($stmt))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[006] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "CREATE TABLE test(id SMALLINT, label CHAR(1))") || !mysqli_stmt_execute($stmt))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[008] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100000, 'a'), (100001, 'b')") ||
+ !mysqli_stmt_execute($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object($warning = mysqli_stmt_get_warnings($stmt)))
+ printf("[010] Expecting mysqli_warning object, got %s/%s\n", gettype($warning), $warning);
+
+ if ('mysqli_warning' !== get_class($warning))
+ printf("[011] Expecting object of type mysqli_warning got type '%s'", get_class($warning));
+
+ if (!method_exists($warning, 'next'))
+ printf("[012] Object mysqli_warning seems to lack method next()\n");
+
+ $i = 0;
+ do {
+
+ if ('' == $warning->message)
+ printf("[013 - %d] Message should not be empty\n", $i);
+
+ if ('' == $warning->sqlstate)
+ printf("[014 - %d] SQL State should not be empty\n", $i);
+
+ if (0 == $warning->errno)
+ printf("[015 - %d] Error number should not be zero\n", $i);
+
+ $i++;
+
+ } while ($warning->next());
+
+ if (2 != $i)
+ printf("[016] Expected 2 warnings, got %d warnings\n", $i);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_get_warnings($stmt)))
+ printf("[015] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_get_warnings(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_get_warnings(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_init.phpt b/ext/mysqli/tests/mysqli_stmt_init.phpt
new file mode 100644
index 0000000000..db5a21cd01
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_init.phpt
@@ -0,0 +1,54 @@
+--TEST--
+mysqli_stmt_init()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--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";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_init()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_init($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_object($stmt = mysqli_stmt_init($link)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($stmt2 = @mysqli_stmt_init($link)))
+ printf("[003a] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_init($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_stmt_init($link)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_close(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_init() expects parameter 1 to be mysqli, object given in %s on line %d
+
+Warning: mysqli_stmt_init(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_insert_id.phpt b/ext/mysqli/tests/mysqli_stmt_insert_id.phpt
new file mode 100644
index 0000000000..1bfe19836b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_insert_id.phpt
@@ -0,0 +1,73 @@
+--TEST--
+mysqli_stmt_insert_id()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_insert_id()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ $stmt = @new mysqli_stmt($link);
+ if (!is_null($tmp = @mysqli_insert_id($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ $stmt = mysqli_stmt_init($link);
+ if (NULL !== ($tmp = @mysqli_stmt_insert_id($stmt)))
+ printf("[003] Expecting NULL/NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1") ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_insert_id($stmt)))
+ printf("[005] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+ mysqli_stmt_close($stmt);
+
+ // no auto_increment column
+ $stmt = mysqli_stmt_init($link);
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (100, 'a')") ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (0 !== ($tmp = mysqli_stmt_insert_id($stmt)))
+ printf("[007] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (mysqli_get_server_version($link) > 50000 &&
+ (!mysqli_stmt_prepare($stmt, "ALTER TABLE test MODIFY id INT NOT NULL AUTO_INCREMENT") ||
+ !mysqli_stmt_execute($stmt))) {
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ } else if (mysqli_get_server_version($link) < 50000){
+ mysqli_query($link, "ALTER TABLE test MODIFY id INT NOT NULL AUTO_INCREMENT");
+ }
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(label) VALUES ('a')") ||
+ !mysqli_stmt_execute($stmt)) {
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ if (0 === ($tmp = mysqli_stmt_insert_id($stmt)))
+ printf("[010] Expecting int/any non zero, got %s/%s\n", gettype($tmp), $tmp);
+ mysqli_stmt_close($stmt);
+
+ mysqli_close($link);
+
+ var_dump(mysqli_stmt_insert_id($stmt));
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_insert_id(): Couldn't fetch mysqli_stmt in %s on line %d
+NULL
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_num_rows.phpt b/ext/mysqli/tests/mysqli_stmt_num_rows.phpt
new file mode 100644
index 0000000000..5cc83977d0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_num_rows.phpt
@@ -0,0 +1,104 @@
+--TEST--
+mysqli_stmt_num_rows()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_num_rows()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_num_rows($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ function func_test_mysqli_stmt_num_rows($stmt, $query, $expected, $offset) {
+
+ if (!mysqli_stmt_prepare($stmt, $query)) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%03d] [%d] %s\n", $offset + 1, mysqli_errno($stmt), mysqli_error($stmt));
+ return false;
+ }
+
+ if (!mysqli_stmt_store_result($stmt)) {
+ printf("[%03d] [%d] %s\n", $offset + 2, mysqli_errno($stmt), mysqli_error($stmt));
+ return false;
+ }
+
+ if ($expected !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[%03d] Expecting %s/%d, got %s/%d\n", $offset + 3,
+ gettype($expected), $expected,
+ gettype($tmp), $tmp);
+
+ mysqli_stmt_free_result($stmt);
+
+ return true;
+ }
+
+ func_test_mysqli_stmt_num_rows($stmt, "SELECT 1 AS a", 1, 10);
+ func_test_mysqli_stmt_num_rows($stmt, "SHOW VARIABLES LIKE '%nixnutz%'", 0, 20);
+ // Note: for statements that return no result set mysqli_num_rows() differs from mysqli_stmt_num_rows() slightly
+ // mysqli_num_rows() failed to fetch the result set and the PHP parameter check makes it return NULL
+ // mysqli_stmt_numrows() has a valid resource to work on and it will return int/0 instead. No bug, but
+ // slightly different behaviour... - if you really check the data types and don't rely on casting like 98% of all PHP
+ // users do.
+ func_test_mysqli_stmt_num_rows($stmt, "INSERT INTO test(id, label) VALUES (100, 'z')", 0, 30);
+
+ if ($res = mysqli_query($link, 'SELECT COUNT(id) AS num FROM test')) {
+ $row = mysqli_fetch_assoc($res);
+ mysqli_free_result($res);
+ func_test_mysqli_stmt_num_rows($stmt, "SELECT id, label FROM test", (int)$row['num'], 40);
+ } else {
+ printf("[050] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+ }
+
+ print "run_tests.php don't fool me with your 'ungreedy' expression '.+?'!\n";
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id FROM test'))
+ printf("[051] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (mysqli_stmt_execute($stmt)) {
+
+ $i = 0;
+ do {
+ if (0 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[53 - %03d] Expecting int/0, got %s/%s\n", $i, gettype($tmp), $tmp);
+ $i++;
+ } while (mysqli_stmt_fetch($stmt));
+
+ if (0 !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[54] Expecting int/0, got %s/%s\n", gettype($tmp), $tmp);
+
+ } else {
+ printf("[055] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_num_rows($stmt)))
+ printf("[056] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+run_tests.php don't fool me with your 'ungreedy' expression '.+?'!
+
+Warning: mysqli_stmt_num_rows(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_param_count.phpt b/ext/mysqli/tests/mysqli_stmt_param_count.phpt
new file mode 100644
index 0000000000..92dfe64321
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_param_count.phpt
@@ -0,0 +1,68 @@
+--TEST--
+mysqli_stmt_param_count()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_param_count()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_param_count($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_param_count($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ function func_test_mysqli_stmt_param_count($stmt, $query, $expected, $offset) {
+
+ if (!mysqli_stmt_prepare($stmt, $query)) {
+ printf("[%03d] [%d] %s\n", $offset, mysqli_stmt_errno($stmt), mysqli_error($stmt));
+ return false;
+ }
+
+ if ($expected !== ($tmp = mysqli_stmt_param_count($stmt)))
+ printf("[%03d] Expecting %s/%d, got %s/%d\n", $offset + 3,
+ gettype($expected), $expected,
+ gettype($tmp), $tmp);
+ return true;
+ }
+
+ func_test_mysqli_stmt_param_count($stmt, "SELECT 1 AS a", 0, 10);
+ func_test_mysqli_stmt_param_count($stmt, "INSERT INTO test(id) VALUES (?)", 1, 20);
+ func_test_mysqli_stmt_param_count($stmt, "INSERT INTO test(id, label) VALUES (?, ?)", 2, 30);
+ func_test_mysqli_stmt_param_count($stmt, "INSERT INTO test(id, label) VALUES (?, '?')", 1, 40);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_param_count($stmt)))
+ printf("[40] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_param_count()))
+ printf("[041] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_param_count(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_param_count(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_prepare.phpt b/ext/mysqli/tests/mysqli_stmt_prepare.phpt
new file mode 100644
index 0000000000..35879591ef
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_prepare.phpt
@@ -0,0 +1,52 @@
+--TEST--
+mysqli_stmt_prepare()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ // Note: No SQL tests here! We can expand one of the *fetch()
+ // tests to a generic SQL test, if we ever need that.
+ // We would duplicate the SQL test cases if we have it here and in one of the
+ // fetch tests, because the fetch tests would have to call prepare/execute etc.
+ // anyway.
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_prepare()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_prepare($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = @mysqli_stmt_prepare($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (false !== ($tmp = mysqli_stmt_prepare($stmt, '')))
+ printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_prepare($stmt, 'SELECT id FROM test')))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_prepare($stmt, "SELECT id FROM test")))
+ printf("[007] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_prepare(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
diff --git a/ext/mysqli/tests/mysqli_stmt_reset.phpt b/ext/mysqli/tests/mysqli_stmt_reset.phpt
new file mode 100644
index 0000000000..903ba23eb0
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_reset.phpt
@@ -0,0 +1,108 @@
+--TEST--
+mysqli_stmt_reset()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ // Note: No SQL tests here! We can expand one of the *fetch()
+ // tests to a generic SQL test, if we ever need that.
+ // We would duplicate the SQL test cases if we have it here and in one of the
+ // fetch tests, because the fetch tests would have to call prepare/execute etc.
+ // anyway.
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_reset()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_reset($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_prepare($stmt, 'SELECT id FROM test')))
+ printf("[005] Expecting boolean/true, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (true !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ $id = null;
+ if (!mysqli_stmt_bind_result($stmt, $id))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_fetch($stmt))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ var_dump($id);
+ mysqli_stmt_close($stmt);
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[011] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, "CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label BLOB, PRIMARY KEY(id))"))
+ printf("[012] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(label) VALUES (?)"))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "b", $label))
+ printf("[014] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $label = 'abc';
+ for ($i = 0; $i < 10; $i++) {
+ if (!mysqli_stmt_send_long_data($stmt, 0, $label))
+ printf("[015 - %d] [%d] %s\n", $i, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+
+ if (!mysqli_stmt_reset($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_execute($stmt))
+ printf("[017] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, "SELECT label FROM test"))
+ printf("[018] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if ($row['label'] != '')
+ printf("[020] Expecting empty string, got string/%s\n", $row['label']);
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_reset($stmt)))
+ printf("[021] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_reset(): invalid object or resource mysqli_stmt
+ in %s on line %d
+int(1)
+
+Warning: mysqli_stmt_reset(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_result_metadata.phpt b/ext/mysqli/tests/mysqli_stmt_result_metadata.phpt
new file mode 100644
index 0000000000..73b67a515f
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_result_metadata.phpt
@@ -0,0 +1,157 @@
+--TEST--
+mysqli_stmt_result_metadata()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_result_metadata()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_result_metadata($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_result_metadata($stmt)))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test"))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!is_object(($res = mysqli_stmt_result_metadata($stmt))))
+ printf("[006] Expecting object, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (2 !== ($tmp = mysqli_num_fields($res)))
+ printf("[007] Expecting int/2, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($field0_fetch = mysqli_fetch_field($res)))
+ printf("[008] Expecting object, got %s/%s, [%d] %s\n",
+ gettype($field0_fetch), $field0_fetch, mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($field0_direct = mysqli_fetch_field_direct($res, 0)))
+ printf("[009] Expecting object, got %s/%s, [%d] %s\n",
+ gettype($field0_direct), $field0_direct, mysqli_errno($link), mysqli_error($link));
+
+ if ($field0_fetch != $field0_direct) {
+ printf("[010] mysqli_fetch_field() differs from mysqli_fetch_field_direct()\n");
+ var_dump($field0_fetch);
+ var_dump($field0_direct);
+ }
+
+ var_dump($field0_fetch);
+
+ if (!is_array($tmp = mysqli_fetch_fields($res)))
+ printf("[011] Expecting array, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (empty($tmp[0]) || empty($tmp[1]) || $tmp[0] != $field0_direct) {
+ printf("[012] mysqli_fetch_fields() return value is suspicious\n");
+ var_dump($tmp);
+ }
+
+ if (!mysqli_field_seek($res, 1))
+ printf("[013] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($field1_direct = mysqli_fetch_field_direct($res, 1)))
+ printf("[014] Expecting object, got %s/%s, [%d] %s\n",
+ gettype($field1_direct), $field1_direct, mysqli_errno($link), mysqli_error($link));
+
+ if ($tmp[1] != $field1_direct) {
+ printf("[015] mysqli_fetch_field_direct() differs from mysqli_fetch_fields()\n");
+ var_dump($field1_direct);
+ var_dump($tmp);
+ }
+
+ if (1 !== ($tmp = mysqli_field_tell($res)))
+ printf("[016] Expecting int/1, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_result_metadata($stmt)))
+ printf("[017] Expecting NULL, got %s/%s\n");
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_get_metadata()))
+ printf("[018] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+
+Warning: mysqli_stmt_result_metadata(): invalid object or resource mysqli_stmt
+ in %s on line %d
+object(stdClass)#5 (%d) {
+ ["name"]=>
+ string(2) "id"
+ ["orgname"]=>
+ string(2) "id"
+ ["table"]=>
+ string(4) "test"
+ ["orgtable"]=>
+ string(4) "test"
+ ["def"]=>
+ string(0) ""
+ ["max_length"]=>
+ int(0)
+ ["length"]=>
+ int(11)
+ ["charsetnr"]=>
+ int(63)
+ ["flags"]=>
+ int(49155)
+ ["type"]=>
+ int(3)
+ ["decimals"]=>
+ int(0)
+}
+
+Warning: mysqli_stmt_result_metadata(): Couldn't fetch mysqli_stmt in %s on line %d
+done!
+--UEXPECTF--
+
+Warning: mysqli_stmt_result_metadata(): invalid object or resource mysqli_stmt
+ in %s on line %d
+object(stdClass)#5 (%d) {
+ [u"name"]=>
+ unicode(2) "id"
+ [u"orgname"]=>
+ unicode(2) "id"
+ [u"table"]=>
+ unicode(4) "test"
+ [u"orgtable"]=>
+ unicode(4) "test"
+ [u"def"]=>
+ unicode(0) ""
+ [u"max_length"]=>
+ int(0)
+ [u"length"]=>
+ int(11)
+ [u"charsetnr"]=>
+ int(63)
+ [u"flags"]=>
+ int(49155)
+ [u"type"]=>
+ int(3)
+ [u"decimals"]=>
+ int(0)
+}
+
+Warning: mysqli_stmt_result_metadata(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt b/ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt
new file mode 100644
index 0000000000..80b9642c74
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_result_metadata_sqltests.phpt
@@ -0,0 +1,229 @@
+--TEST--
+mysqli_stmt_result_metadata() - non SELECT statements
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+ require('table.inc');
+
+ function testStatement($offset, $link, $sql, $expected_lib, $expected_mysqlnd, $check_mysqlnd, $compare) {
+
+ if (!$stmt = mysqli_stmt_init($link)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset, $sql,
+ mysqli_errno($link), mysqli_error($link));
+ return false;
+ }
+
+ if (!@mysqli_stmt_prepare($stmt, $sql)) {
+ /* Not all server versions will support all statements */
+ /* Failing to prepare is OK */
+ return true;
+ }
+ $res = mysqli_stmt_result_metadata($stmt);
+ if (empty($expected_lib) && (false !== $res)) {
+ printf("[%04d - %s] No metadata expected\n",
+ $offset + 1, $sql);
+ return false;
+ } else if (!empty($expected_lib) && (false == $res)) {
+ printf("[%04d - %s] Metadata expected\n",
+ $offset + 2, $sql);
+ return false;
+ }
+ if (!empty($expected_lib)) {
+ if (!is_object($res)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset + 3, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ if (get_class($res) != 'mysqli_result') {
+ printf("[%04d - %s] Expecting object/mysqli_result got object/%s\n",
+ $offset + 4, $sql, get_class($res));
+ return false;
+ }
+
+ $meta = array(
+ 'num_fields' => mysqli_num_fields($res),
+ 'fetch_field' => mysqli_fetch_field($res),
+ 'fetch_field_direct0' => mysqli_fetch_field_direct($res, 0),
+ 'fetch_field_direct1' => @mysqli_fetch_field_direct($res, 1),
+ 'fetch_fields' => count(mysqli_fetch_fields($res)),
+ 'field_count' => $res->field_count,
+ 'field_seek-1' => @mysqli_field_seek($res, -1),
+ 'field_seek0' => mysqli_field_seek($res, 0),
+ 'field_tell' => mysqli_field_tell($res),
+ );
+ if (is_object($meta['fetch_field'])) {
+ $meta['fetch_field']->charsetnr = 'ignore';
+ $meta['fetch_field']->flags = 'ignore';
+ }
+ if (is_object($meta['fetch_field_direct0'])) {
+ $meta['fetch_field_direct0']->charsetnr = 'ignore';
+ $meta['fetch_field_direct0']->flags = 'ignore';
+ }
+ if (is_object($meta['fetch_field_direct1'])) {
+ $meta['fetch_field_direct1']->charsetnr = 'ignore';
+ $meta['fetch_field_direct1']->flags = 'ignore';
+ }
+ mysqli_free_result($res);
+
+ if ($meta != $expected_lib) {
+ printf("[%04d - %s] Metadata differes from expected values\n",
+ $offset + 5, $sql);
+ var_dump($meta);
+ var_dump($expected_lib);
+ return false;
+ }
+ }
+
+ if (function_exists('mysqli_stmt_get_result')) {
+ /* mysqlnd only */
+ if (!mysqli_stmt_execute($stmt)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset + 6, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ $res = mysqli_stmt_get_result($stmt);
+ if (false === $res && !empty($expected_mysqlnd)) {
+ printf("[%04d - %s] Expecting resultset [%d] %s\n",
+ $offset + 7, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ } else if (empty($expected_mysqlnd) && false !== $res) {
+ printf("[%04d - %s] Unexpected resultset [%d] %s\n",
+ $offset + 8, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+
+ if (!is_object($res)) {
+ printf("[%04d - %s] [%d] %s\n",
+ $offset + 9, $sql,
+ mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ return false;
+ }
+ if ('mysqli_result' != get_class($res)) {
+ printf("[%04d - %s] Expecting object/mysqli_result got object/%s\n",
+ $offset + 10, $sql,
+ get_class($res));
+ return false;
+ }
+
+ $meta_res = array(
+ 'num_fields' => mysqli_num_fields($res),
+ 'fetch_field' => mysqli_fetch_field($res),
+ 'fetch_field_direct0' => mysqli_fetch_field_direct($res, 0),
+ 'fetch_field_direct1' => @mysqli_fetch_field_direct($res, 1),
+ 'fetch_fields' => count(mysqli_fetch_fields($res)),
+ 'field_count' => mysqli_field_count($link),
+ 'field_seek-1' => @mysqli_field_seek($res, -1),
+ 'field_seek0' => mysqli_field_seek($res, 0),
+ 'field_tell' => mysqli_field_tell($res),
+ );
+ if (is_object($meta_res['fetch_field'])) {
+ $meta_res['fetch_field']->charsetnr = 'ignore';
+ $meta_res['fetch_field']->flags = 'ignore';
+ }
+ if (is_object($meta_res['fetch_field_direct0'])) {
+ $meta_res['fetch_field_direct0']->charsetnr = 'ignore';
+ $meta_res['fetch_field_direct0']->flags = 'ignore';
+ }
+ if (is_object($meta_res['fetch_field_direct1'])) {
+ $meta_res['fetch_field_direct1']->charsetnr = 'ignore';
+ $meta_res['fetch_field_direct1']->flags = 'ignore';
+ }
+ mysqli_free_result($res);
+ if ($check_mysqlnd && $meta_res != $expected_mysqlnd) {
+ printf("[%04d - %s] Metadata differs from expected\n",
+ $offset + 11, $sql);
+ var_dump($meta_res);
+ var_dump($expected_mysqlnd);
+ } else {
+ if ($meta_res['field_count'] < 1) {
+ printf("[%04d - %s] Metadata seems wrong, no fields?\n",
+ $offset + 12, $sql);
+ var_dump($meta_res);
+ var_dump(mysqli_fetch_assoc($res));
+ }
+ }
+
+ if ($compare && $meta_res != $meta) {
+ printf("[%04d - %s] Metadata returned by mysqli_stmt_result_metadata() and mysqli_stmt_get_result() differ\n",
+ $offset + 13, $sql);
+ var_dump($meta_res);
+ var_dump($meta);
+ }
+
+ }
+
+ mysqli_stmt_close($stmt);
+ return true;
+ }
+
+ /* Note: very weak testing, we accept almost any result */
+
+ testStatement(100, $link, 'ANALYZE TABLE test', array(), array(1), false, false);
+ testStatement(120, $link, 'OPTIMIZE TABLE test', array(), array(1), false, false);
+ testStatement(140, $link, 'REPAIR TABLE test', array(), array(1), false, false);
+
+ testStatement(160, $link, 'SHOW AUTHORS', array(), array(1), false, false);
+ testStatement(180, $link, 'SHOW CHARACTER SET', array(), array(1), false, false);
+ testStatement(200, $link, 'SHOW COLLATION', array(), array(1), false, false);
+ testStatement(220, $link, 'SHOW CONTRIBUTORS', array(), array(1), false, false);
+ testStatement(240, $link, 'SHOW CREATE DATABASE ' . $db, array(), array(1), false, false);
+ testStatement(260, $link, 'SHOW DATABASES', array(), array(1), false, false);
+ testStatement(280, $link, 'SHOW ENGINE InnoDB STATUS', array(), array(1), false, false);
+ testStatement(300, $link, 'SHOW ENGINES', array(), array(1), false, false);
+ testStatement(320, $link, 'SHOW PLUGINS', array(), array(1), false, false);
+ testStatement(340, $link, 'SHOW PROCESSLIST', array(), array(1), false, false);
+ testStatement(360, $link, 'SHOW FULL PROCESSLIST', array(), array(1), false, false);
+ testStatement(380, $link, 'SHOW STATUS', array(), array(1), false, false);
+ testStatement(400, $link, 'SHOW TABLE STATUS', array(), array(1), false, false);
+ testStatement(420, $link, 'SHOW TABLE STATUS', array(), array(1), false, false);
+ testStatement(440, $link, 'SHOW TABLES', array(), array(1), false, false);
+ testStatement(460, $link, 'SHOW OPEN TABLES', array(), array(1), false, false);
+ testStatement(460, $link, 'SHOW VARIABLES', array(), array(1), false, false);
+
+ $field0 = new stdClass();
+ $field0->name = 'id';
+ $field0->orgname = 'id';
+ $field0->table = 'test';
+ $field0->orgtable = 'test';
+ $field0->def = '';
+ $field0->max_length = 0;
+ $field0->length = 11;
+ $field0->charsetnr = 'ignore';
+ $field0->flags = 'ignore';
+ $field0->type = MYSQLI_TYPE_LONG;
+ $field0->decimals = 0;
+ $meta_lib = array(
+ 'num_fields' => 1,
+ 'fetch_field' => $field0,
+ 'fetch_field_direct0' => $field0,
+ 'fetch_field_direct1' => false,
+ 'fetch_fields' => 1,
+ 'field_count' => 1,
+ 'field_seek-1' => false,
+ 'field_seek0' => true,
+ 'field_tell' => 0,
+ );
+ $meta_mysqlnd = $meta_lib;
+ testStatement(480, $link, 'SELECT id FROM test', $meta_lib, $meta_mysqlnd, true, true);
+
+ testStatement(500, $link, 'CHECKSUM TABLE test', array(), array(1), false, false);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+done!
+--UEXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt
new file mode 100644
index 0000000000..9e6cef0555
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_send_long_data.phpt
@@ -0,0 +1,129 @@
+--TEST--
+mysqli_stmt_send_long_data()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_send_long_data()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_send_long_data($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = @mysqli_stmt_send_long_data($stmt, '')))
+ printf("[004] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_query($link, "DROP TABLE IF EXISTS test"))
+ printf("[005] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label LONGBLOB, PRIMARY KEY(id)) ENGINE = %s", $engine)))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[007] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "ib", $id, $label))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "max_allowed_packet"'))
+ printf("[009] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[011] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ // let's ignore upper limits for LONGBLOB (2^32) ...
+ // maximum packet size up to which we test is 10M
+ $tmp = '';
+ $blob = '';
+ for ($i = 0; $i < 1024; $i++) {
+ $tmp .= 'a';
+ }
+
+ $limit = min(floor($max_allowed_packet / 1024 / 2), 10240);
+ for ($i = 0; $i < $limit; $i++)
+ $blob .= $tmp;
+ /*
+ if (floor($max_allowed_packet / 1024) <= 10240) {
+ $limit = strlen($blob) - $max_allowed_packet - 1;
+ for ($i = 0; $i < $limit; $i++)
+ $blob .= 'a';
+ }
+ */
+ assert(strlen($blob) <= $max_allowed_packet);
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, -1, $blob)))
+ printf("[012] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, PHP_INT_MAX + 1, $blob)))
+ printf("[013] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, 999, $blob)))
+ printf("[014] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob)))
+ printf("[015] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[016] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ mysqli_stmt_close($stmt);
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[017] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (1 != ($tmp = mysqli_num_rows($res)))
+ printf("[018] Expecting 1 rows, mysqli_num_rows() reports %d rows. [%d] %s\n",
+ $tmp, mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[019] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (empty($row['id']) || empty($row['label']) || ($row['id'] != 1))
+ printf("[020] Record seems to be incomplete\n");
+
+ if ($blob != $row['label'])
+ printf("[021] Blob value has not been stored properly!\n");
+
+ if (NULL !== ($tmp = @mysqli_stmt_send_long_data($stmt, '')))
+ printf("[022] Expecting NULL, got %s/%s\n");
+
+ /* Check that the function alias exists. It's a deprecated function,
+ but we have not announce the removal so far, therefore we need to check for it */
+ if (!is_null($tmp = @mysqli_send_long_data()))
+ printf("[023] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_send_long_data(): Invalid parameter number in %s on line %d
+
+Warning: mysqli_stmt_send_long_data(): Invalid parameter number in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt
new file mode 100644
index 0000000000..9d2aa397fd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_libmysql.phpt
@@ -0,0 +1,95 @@
+--TEST--
+mysqli_stmt_send_long_data() - exceed packet size, libmysql - bug #26824
+--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");
+?>
+--FILE--
+<?php
+ 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, "DROP TABLE IF EXISTS test"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label LONGBLOB, PRIMARY KEY(id)) ENGINE = %s", $engine)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "ib", $id, $label))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "max_allowed_packet"'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[008] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ // let's ignore upper limits for LONGBLOB (2^32) ...
+ // maximum packet size up to which we test is 10M
+ $tmp = '';
+ $blob = '';
+ for ($i = 0; $i < 1024; $i++) {
+ $tmp .= 'a';
+ }
+
+ $limit = min(floor($max_allowed_packet / 1024 / 2), 10240);
+ for ($i = 0; $i < $limit; $i++)
+ $blob .= $tmp;
+
+ assert(strlen($blob) <= $max_allowed_packet);
+
+ if (true != ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob)))
+ printf("[009] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /*
+ TODO - we skip this part of the test for now, because of bugs.mysql.com/26824
+ if (floor($max_allowed_packet / 1024 / 2) <= 10240) {
+ // test with a blob smaller than 10M allows us to test
+ // for too long packages without wasting too much memory
+ $limit = $max_allowed_packet - strlen($blob) + 1;
+ $blob2 = $blob;
+ for ($i = 0; $i < $limit; $i++)
+ $blob2 .= 'b';
+
+ assert(strlen($blob2) > $max_allowed_packet);
+
+ if (true != ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob2)))
+ printf("[011] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 2;
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[012] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ */
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt
new file mode 100644
index 0000000000..1600729250
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_send_long_data_packet_size_mysqlnd.phpt
@@ -0,0 +1,100 @@
+--TEST--
+mysqli_stmt_send_long_data() - exceed packet size, mysqlnd
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+
+if (!stristr(mysqli_get_client_info(), 'mysqlnd'))
+ die("skip: warnings only available in mysqlnd");
+?>
+--FILE--
+<?php
+ 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, "DROP TABLE IF EXISTS test"))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT NOT NULL AUTO_INCREMENT, label LONGBLOB, PRIMARY KEY(id)) ENGINE = %s", $engine)))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)"))
+ printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = null;
+ $label = null;
+ if (!mysqli_stmt_bind_param($stmt, "ib", $id, $label))
+ printf("[005] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$res = mysqli_query($link, 'SHOW VARIABLES LIKE "max_allowed_packet"'))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!$row = mysqli_fetch_assoc($res))
+ printf("[007] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (0 === ($max_allowed_packet = (int)$row['Value']))
+ printf("[008] Cannot determine max_allowed_packet size and/or bogus max_allowed_packet setting used.\n");
+
+ // let's ignore upper limits for LONGBLOB (2^32) ...
+ // maximum packet size up to which we test is 10M
+ $tmp = '';
+ $blob = '';
+ $tmp = str_repeat('a', 1024);
+
+ $limit = min(floor($max_allowed_packet / 1024 / 2), 10240);
+ $blob = str_repeat($tmp, $limit);
+
+ assert(strlen($blob) <= $max_allowed_packet);
+
+ if (true !== ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob)))
+ printf("[009] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 1;
+ if (true !== mysqli_stmt_execute($stmt))
+ printf("[010] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ /*
+ TODO - we skip this because of the open bug http://bugs.mysql.com/bug.php?id=26824
+ It would always fail.
+
+ This should be added to the EXPECTF, if you reactivate the test
+Warning: mysqli_stmt_send_long_data(): Skipped %d bytes. Last command STMT_SEND_LONG_DATA hasn't consumed all the output from the server in %s on line %d
+
+Warning: mysqli_stmt_send_long_data(): There was an error while sending long data. Probably max_allowed_packet_size is smaller than the data. You have to increase it or send smaller chunks of data. Answer was %d bytes long. in %s on line %d
+
+
+
+ if (floor($max_allowed_packet / 1024 / 2) <= 10240) {
+ // test with a blob smaller than 10M allows us to test
+ // for too long packages without wasting too much memory
+ $limit = $max_allowed_packet - strlen($blob) + 1;
+ $blob2 = $blob;
+ $blob2 .= str_repeat('b', $limit);
+
+ assert(strlen($blob2) > $max_allowed_packet);
+
+ if (false !== ($tmp = mysqli_stmt_send_long_data($stmt, 1, $blob2)))
+ printf("[011] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ $id = 2;
+ if (false !== ($tmp = mysqli_stmt_execute($stmt)))
+ printf("[012] Expecting boolean/false, got %s/%s, [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+ }
+ */
+ mysqli_stmt_close($stmt);
+ mysqli_close($link);
+
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_sqlstate.phpt b/ext/mysqli/tests/mysqli_stmt_sqlstate.phpt
new file mode 100644
index 0000000000..b946d31f20
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_sqlstate.phpt
@@ -0,0 +1,59 @@
+--TEST--
+mysqli_stmt_sqlstate()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_sqlstate()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_sqlstate($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stmt_sqlstate($link, '')))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (NULL !== ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, "SELECT id FROM test"))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ('00000' !== ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[007] Expecting string/00000, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (mysqli_stmt_prepare($stmt, "SELECT believe_me FROM i_dont_belive_that_this_table_exists"))
+ printf("[008] Should fail! [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if ('' === ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[009] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ mysqli_stmt_close($stmt);
+
+ if (NULL !== ($tmp = mysqli_stmt_sqlstate($stmt)))
+ printf("[010] Expecting NULL, got %s/%s\n");
+
+ mysqli_close($link);
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_stmt_sqlstate(): invalid object or resource mysqli_stmt
+ in %s on line %d
+
+Warning: mysqli_stmt_sqlstate(): Couldn't fetch mysqli_stmt in %s on line %d
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_store_result.phpt b/ext/mysqli/tests/mysqli_stmt_store_result.phpt
new file mode 100644
index 0000000000..57d18424bd
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_store_result.phpt
@@ -0,0 +1,86 @@
+--TEST--
+mysqli_stmt_store_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_stmt_store_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_stmt_store_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!is_null($tmp = @mysqli_stmt_store_result(new mysqli_stmt())))
+ printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[004] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ // stmt object status test
+ if (NULL !== ($tmp = @mysqli_stmt_store_result($stmt)))
+ printf("[005] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'INSERT INTO test(id, label) VALUES (100, "z")') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[006] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (true !== ($tmp = @mysqli_stmt_store_result($stmt)))
+ printf("[007] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!mysqli_stmt_prepare($stmt, 'SELECT id, label FROM test ORDER BY id') ||
+ !mysqli_stmt_execute($stmt))
+ printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!$link_buf = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[009] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error());
+
+ if (!$stmt_buf = mysqli_stmt_init($link_buf))
+ printf("[010] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!mysqli_stmt_prepare($stmt_buf, "SELECT id, label FROM test ORDER BY id") ||
+ !mysqli_stmt_execute($stmt_buf))
+ printf("[011] [%d] %s\n", mysqli_stmt_errno($stmt_buf), mysqli_stmt_error($stmt_buf));
+
+ $id = $label = $id_buf = $label_buf = null;
+ if (!mysqli_stmt_bind_result($stmt, $id, $label))
+ printf("[012] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt));
+
+ if (!mysqli_stmt_bind_result($stmt_buf, $id_buf, $label_buf))
+ printf("[013] [%d] %s\n", mysqli_stmt_errno($stmt_buf), mysqli_stmt_error($stmt_buf));
+
+ while (mysqli_stmt_fetch($stmt)) {
+ if (!mysqli_stmt_fetch($stmt_buf)) {
+ printf("[014] Unbuffered statement indicates more rows than buffered, [%d] %s\n",
+ mysqli_stmt_errno($stmt_buf), mysqli_stmt_error($stmt_buf));
+ }
+ if ($id !== $id_buf)
+ printf("[015] unbuffered '%s'/%s, buffered '%s'/%s\n",
+ $id, gettype($id), $id_buf, gettype($id_buf));
+ if ($label !== $label_buf)
+ printf("[016] unbuffered '%s'/%s, buffered '%s'/%s\n",
+ $label, gettype($label), $label_buf, gettype($label_buf));
+ }
+
+ mysqli_stmt_close($stmt);
+ mysqli_stmt_close($stmt_buf);
+
+ if (NULL !== ($tmp = @mysqli_stmt_store_result($stmt)))
+ printf("[017] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ mysqli_close($link);
+ mysqli_close($link_buf);
+ print "done!";
+?>
+--EXPECTF--
+done! \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_stmt_unclonable.phpt b/ext/mysqli/tests/mysqli_stmt_unclonable.phpt
new file mode 100644
index 0000000000..5aa93b146b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_unclonable.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Trying to clone mysqli_stmt object
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ if (!$link = mysqli_connect($host, $user, $passwd, $db, $port, $socket))
+ printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
+ $host, $user, $db, $port, $socket);
+
+ if (!$stmt = mysqli_stmt_init($link))
+ printf("[002] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ /* no, still bails out */
+ $stmt_clone = clone $stmt;
+ print "done!";
+?>
+--EXPECTF--
+Fatal error: Trying to clone an uncloneable object of class mysqli_stmt in %s on line %d \ No newline at end of file
diff --git a/ext/mysqli/tests/mysqli_store_result.phpt b/ext/mysqli/tests/mysqli_store_result.phpt
new file mode 100644
index 0000000000..13e2a1182a
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_store_result.phpt
@@ -0,0 +1,60 @@
+--TEST--
+mysqli_store_result()
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once('skipifemb.inc');
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+ include "connect.inc";
+
+ $tmp = NULL;
+ $link = NULL;
+
+ if (!is_null($tmp = @mysqli_store_result()))
+ printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ if (!is_null($tmp = @mysqli_store_result($link)))
+ printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ require('table.inc');
+
+ if (!$res = mysqli_real_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[003] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (!is_object($res = mysqli_store_result($link)))
+ printf("[004] Expecting object, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (true !== ($tmp = mysqli_data_seek($res, 2)))
+ printf("[005] Expecting boolean/true, got %s/%s. [%d] %s\n",
+ gettype($tmp), $tmp, mysqli_errno($link), mysqli_error($link));
+
+ mysqli_free_result($res);
+
+ if (!mysqli_query($link, "DELETE FROM test"))
+ printf("[006] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($res = mysqli_store_result($link)))
+ printf("[007] Expecting boolean/false, got %s/%s. [%d] %s\n",
+ gettype($res), $res, mysqli_errno($link), mysqli_error($link));
+
+ if (!$res = mysqli_query($link, "SELECT id, label FROM test ORDER BY id"))
+ printf("[008] [%d] %s\n", mysqli_errno($link), mysqli_error($link));
+
+ if (false !== ($tmp = mysqli_data_seek($res, 1)))
+ printf("[009] Expecting boolean/false, got %s/%s\n",
+ gettype($tmp), $tmp);
+
+ mysqli_close($link);
+
+ if (NULL !== ($tmp = mysqli_store_result($link)))
+ printf("[010] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp);
+
+ print "done!";
+?>
+--EXPECTF--
+Warning: mysqli_store_result(): Couldn't fetch mysqli in %s on line %d
+done! \ No newline at end of file