1--TEST-- 2mysqli_stmt_bind_result() 3--SKIPIF-- 4<?php 5require_once('skipif.inc'); 6require_once('skipifemb.inc'); 7require_once('skipifconnectfailure.inc'); 8?> 9--FILE-- 10<?php 11 require_once("connect.inc"); 12 13 $hint_str_or_unicode = (version_compare(PHP_VERSION, '5.9.9', '>') == 1) ? "unicode":"string"; 14 15 $tmp = NULL; 16 $link = NULL; 17 18 if (!is_null($tmp = @mysqli_stmt_bind_result())) 19 printf("[001] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); 20 21 if (!is_null($tmp = @mysqli_stmt_bind_result($link))) 22 printf("[002] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); 23 24 require('table.inc'); 25 26 $stmt = mysqli_stmt_init($link); 27 if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1")) 28 printf("[002a] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 29 30 if (!is_null($tmp = @mysqli_stmt_bind_result($stmt))) 31 printf("[002b] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); 32 33 mysqli_stmt_close($stmt); 34 $stmt = mysqli_stmt_init($link); 35 36 $id = null; 37 $label = null; 38 $foo = null; 39 40 if (!is_null($tmp = mysqli_stmt_bind_result($stmt))) 41 printf("[003] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); 42 43 if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test ORDER BY id LIMIT 1")) 44 printf("[004] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 45 46 if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id))) 47 printf("[005] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); 48 49 if (true !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label))) 50 printf("[006] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 51 52 if (false !== ($tmp = mysqli_stmt_bind_result($stmt, $id, $label, $foo))) 53 printf("[007] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); 54 55 if (!mysqli_stmt_execute($stmt)) 56 printf("[008] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 57 58 while (mysqli_stmt_fetch($stmt)) { 59 var_dump($id); 60 var_dump($label); 61 } 62 mysqli_stmt_close($stmt); 63 64 65 function func_mysqli_stmt_bind_result($link, $engine, $bind_type, $sql_type, $bind_value, $offset, $type_hint = null) { 66 67 if (!mysqli_query($link, "DROP TABLE IF EXISTS test")) { 68 printf("[%04d] [%d] %s\n", $offset, mysqli_errno($link), mysqli_error($link)); 69 return false; 70 } 71 72 if (!mysqli_query($link, sprintf("CREATE TABLE test(id INT, label %s, PRIMARY KEY(id)) ENGINE = %s", $sql_type, $engine))) { 73 // don't bail - column type might not be supported by the server, ignore this 74 return false; 75 } 76 77 if (!$stmt = mysqli_stmt_init($link)) { 78 printf("[%04d] [%d] %s\n", $offset + 1, mysqli_errno($link), mysqli_error($link)); 79 return false; 80 } 81 82 if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (?, ?)")) { 83 printf("[%04d] [%d] %s\n", $offset + 2, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 84 return false; 85 } 86 87 $id = null; 88 if (!mysqli_stmt_bind_param($stmt, "i" . $bind_type, $id, $bind_value)) { 89 printf("[%04d] [%d] %s\n", $offset + 3, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 90 mysqli_stmt_close($stmt); 91 return false; 92 } 93 94 for ($id = 1; $id < 4; $id++) { 95 if (!mysqli_stmt_execute($stmt)) { 96 printf("[%04d] [%d] %s\n", $offset + 3 + $id, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 97 mysqli_stmt_close($stmt); 98 return false; 99 } 100 } 101 mysqli_stmt_close($stmt); 102 103 $stmt = mysqli_stmt_init($link); 104 105 if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) { 106 printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 107 mysqli_stmt_close($stmt); 108 return false; 109 } 110 111 if (!mysqli_stmt_execute($stmt)) { 112 printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 113 mysqli_stmt_close($stmt); 114 return false; 115 } 116 117 $result = mysqli_stmt_result_metadata($stmt); 118 119 $bind_res = null; 120 if (!mysqli_stmt_bind_result($stmt, $id, $bind_res)) { 121 printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 122 mysqli_stmt_close($stmt); 123 return false; 124 } 125 $num = 0; 126 $fields = mysqli_fetch_fields($result); 127 128 while (mysqli_stmt_fetch($stmt)) { 129 if (!gettype($bind_res)=="unicode") { 130 if ($bind_res !== $bind_value && (!$type_hint || ($type_hint !== gettype($bind_res)))) { 131 printf("[%04d] [%d] Expecting %s/'%s' [type hint = %s], got %s/'%s'\n", 132 $offset + 10, $num, 133 gettype($bind_value), $bind_value, $type_hint, 134 gettype($bind_res), $bind_res); 135 mysqli_stmt_close($stmt); 136 return false; 137 } 138 } 139 $num++; 140 } 141 142 if ($num != 3) { 143 printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n", 144 $offset + 11, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num); 145 mysqli_stmt_close($stmt); 146 return false; 147 } 148 149 mysqli_stmt_close($stmt); 150 return true; 151 } 152 153 154 function func_mysqli_stmt_bind_make_string($len) { 155 156 $ret = ''; 157 for ($i = 0; $i < $len; $i++) 158 $ret .= chr(mt_rand(65, 90)); 159 160 return $ret; 161 } 162 163 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", -11, 20); 164 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", NULL, 40); 165 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", 1, 60); 166 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", NULL, 80); 167 168 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", 1, 100); 169 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", NULL, 120); 170 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", 0, 140); 171 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", NULL, 160); 172 173 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", -32768, 180); 174 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", 32767, 200); 175 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", NULL, 220); 176 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 240); 177 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 260); 178 179 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", -8388608, 280, "integer"); 180 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", 8388607, 300, "integer"); 181 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", NULL, 320); 182 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", 16777215, 340, "integer"); 183 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", NULL, 360); 184 185 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? max(-1 * PHP_INT_MAX + 1, -2147483648) : 1, 380); 186 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", -2147483647, 400, "integer"); 187 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? min(2147483647, PHP_INT_MAX) : 1, 420); 188 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", NULL, 440); 189 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, 2147483647) : 1, 460); 190 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", 4294967295, 480, (defined("PHP_INT_MAX") && (4294967295 > PHP_INT_MAX)) ? "string" : null); 191 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", NULL, 500); 192 193 /* test is broken too: we bind "integer" but value is a float 194 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -9223372036854775808, 520); 195 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 18446744073709551615, 560); 196 */ 197 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", NULL, 540); 198 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", NULL, 580); 199 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1, 1780); 200 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 1, 1800); 201 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 1820); 202 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", PHP_INT_MAX, 1840); 203 func_mysqli_stmt_bind_result($link, $engine, "s", "BIGINT UNSIGNED", "18446744073709551615", 1860); 204 func_mysqli_stmt_bind_result($link, $engine, "s", "BIGINT", "-9223372036854775808", 1880); 205 206 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", -9223372036854775808 - 1.1, 600); 207 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", NULL, 620); 208 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED", 18446744073709551615 + 1.1, 640); 209 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 660); 210 211 // Yes, we need the temporary variable. The PHP casting will fouls us otherwise. 212 $tmp = strval('-99999999.99'); 213 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", $tmp, 680, "string"); 214 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", NULL, 700); 215 $tmp = strval('99999999.99'); 216 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", $tmp , 720, "string"); 217 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 740); 218 $tmp = strval('-99999999.99'); 219 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 760, "string"); 220 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 780); 221 $tmp = strval('99999999.99'); 222 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", $tmp, 800, "string"); 223 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 820); 224 225 // don't care about date() strict TZ warnings... 226 func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", @date('Y-m-d'), 840); 227 func_mysqli_stmt_bind_result($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 860); 228 func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", NULL, 880); 229 230 func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 900); 231 func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 920); 232 func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", NULL, 940); 233 234 func_mysqli_stmt_bind_result($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 960); 235 236 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", @date('H:i:s'), 980); 237 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 1000); 238 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", NULL, 1020); 239 240 $tmp = intval(@date('Y')); 241 func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", $tmp, 1040, "integer"); 242 func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR NOT NULL", $tmp, 1060, "integer"); 243 func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", NULL, 1080); 244 245 $string255 = func_mysqli_stmt_bind_make_string(255); 246 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", "a", 1110, $hint_str_or_unicode); 247 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(255)", $string255, 1120, $hint_str_or_unicode); 248 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1) NOT NULL", "a", 1140, $hint_str_or_unicode); 249 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", NULL, 1160); 250 251 $string65k = func_mysqli_stmt_bind_make_string(65535); 252 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", "a", 1180, $hint_str_or_unicode); 253 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(255)", $string255, 1200, $hint_str_or_unicode); 254 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(65635)", $string65k, 1220, $hint_str_or_unicode); 255 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 1240, $hint_str_or_unicode); 256 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", NULL, 1260); 257 258 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", "a", 1280); 259 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", chr(0), 1300); 260 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1) NOT NULL", "b", 1320); 261 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", NULL, 1340); 262 263 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", "a", 1360); 264 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", chr(0), 1380); 265 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 1400); 266 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", NULL, 1420); 267 268 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", "a", 1440); 269 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", chr(0), 1460); 270 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB NOT NULL", "b", 1480); 271 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", NULL, 1500); 272 273 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", "a", 1520, $hint_str_or_unicode); 274 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT NOT NULL", "a", 1540, $hint_str_or_unicode); 275 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", NULL, 1560, $hint_str_or_unicode); 276 277 // Note: you cannot insert any blob values this way. But you can check the API at least partly this way 278 // Extra BLOB tests are in mysqli_stmt_send_long() 279 func_mysqli_stmt_bind_result($link, $engine, "b", "BLOB", b"", 1580); 280 func_mysqli_stmt_bind_result($link, $engine, "b", "TEXT", "", 1600, $hint_str_or_unicode); 281 func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMBLOB", b"", 1620); 282 func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMTEXT", "", 1640, $hint_str_or_unicode); 283 284 /* Is this one related? http://bugs.php.net/bug.php?id=35759 */ 285 if (($IS_MYSQLND) || (!$IS_MYSQLND && (ini_get('memory_limit') > 4294967296))) { 286 /* NOTE: the MySQL Client Library - not mysqlnd - will allocate 287 a hugge max_length(type) = 4GB bind buffer */ 288 func_mysqli_stmt_bind_result($link, $engine, "b", "LONGBLOB", "", 1660); 289 func_mysqli_stmt_bind_result($link, $engine, "b", "LONGTEXT", "", 1680, $hint_str_or_unicode); 290 } 291 292 func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", "a", 1700, $hint_str_or_unicode); 293 func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", NULL, 1720, $hint_str_or_unicode); 294 func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", "a", 1740, $hint_str_or_unicode); 295 func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", NULL, 1760, $hint_str_or_unicode); 296 297 if (mysqli_get_server_version($link) >= 50600) 298 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", "13:31:34.123456", 1770, "13:31:34"); 299 300 /* Check that the function alias exists. It's a deprecated function, 301 but we have not announce the removal so far, therefore we need to check for it */ 302 if (!is_null($tmp = @mysqli_stmt_bind_result())) 303 printf("[3000] Expecting NULL, got %s/%s\n", gettype($tmp), $tmp); 304 305 $stmt = mysqli_stmt_init($link); 306 if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (1000, 'z')")) 307 printf("[3001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 308 309 $id = null; 310 if (false !== @mysqli_stmt_bind_result($stmt, $id)) 311 printf("[3002] Bind result should not be allowed"); 312 313 mysqli_stmt_close($stmt); 314 315 mysqli_close($link); 316 print "done!"; 317?> 318--CLEAN-- 319<?php 320 require_once("clean_table.inc"); 321?> 322--EXPECTF-- 323Warning: mysqli_stmt_bind_result(): invalid object or resource mysqli_stmt 324 in %s on line %d 325 326Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d 327 328Warning: mysqli_stmt_bind_result(): Number of bind variables doesn't match number of fields in prepared statement in %s on line %d 329int(1) 330%s(1) "a" 331done!