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