1--TEST-- 2mysqli_stmt_bind_result() 3--EXTENSIONS-- 4mysqli 5--SKIPIF-- 6<?php 7require_once 'skipifconnectfailure.inc'; 8?> 9--FILE-- 10<?php 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 return false; 84 } 85 86 for ($id = 1; $id < 4; $id++) { 87 if (!mysqli_stmt_execute($stmt)) { 88 printf("[%04d] [%d] %s\n", $offset + 3 + $id, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 89 return false; 90 } 91 } 92 mysqli_stmt_close($stmt); 93 94 $stmt = mysqli_stmt_init($link); 95 96 if (!mysqli_stmt_prepare($stmt, "SELECT id, label FROM test")) { 97 printf("[%04d] [%d] %s\n", $offset + 7, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 98 return false; 99 } 100 101 if (!mysqli_stmt_execute($stmt)) { 102 printf("[%04d] [%d] %s\n", $offset + 8, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 103 return false; 104 } 105 106 $bind_res = null; 107 if (!mysqli_stmt_bind_result($stmt, $id, $bind_res)) { 108 printf("[%04d] [%d] %s\n", $offset + 9, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 109 return false; 110 } 111 $num = 0; 112 113 while (mysqli_stmt_fetch($stmt)) { 114 if ($bind_res !== $bind_value && (!$type_hint || ($type_hint !== gettype($bind_res)))) { 115 printf("[%04d] [%d] Expecting %s/'%s' [type hint = %s], got %s/'%s'\n", 116 $offset + 10, $num, 117 gettype($bind_value), $bind_value, $type_hint, 118 gettype($bind_res), $bind_res); 119 return false; 120 } 121 $num++; 122 } 123 124 if ($num != 3) { 125 printf("[%04d] [%d] %s, expecting 3 results, got only %d results\n", 126 $offset + 11, mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt), $num); 127 return false; 128 } 129 130 return true; 131 } 132 133 134 function func_mysqli_stmt_bind_make_string($len) { 135 136 $ret = ''; 137 for ($i = 0; $i < $len; $i++) 138 $ret .= chr(mt_rand(65, 90)); 139 140 return $ret; 141 } 142 143 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", -11, 20); 144 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT", NULL, 40); 145 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", 1, 60); 146 func_mysqli_stmt_bind_result($link, $engine, "i", "TINYINT UNSIGNED", NULL, 80); 147 148 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", 1, 100); 149 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOL", NULL, 120); 150 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", 0, 140); 151 func_mysqli_stmt_bind_result($link, $engine, "i", "BOOLEAN", NULL, 160); 152 153 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", -32768, 180); 154 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", 32767, 200); 155 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT", NULL, 220); 156 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", 65535, 240); 157 func_mysqli_stmt_bind_result($link, $engine, "i", "SMALLINT UNSIGNED", NULL, 260); 158 159 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", -8388608, 280, "integer"); 160 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", 8388607, 300, "integer"); 161 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT", NULL, 320); 162 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", 16777215, 340, "integer"); 163 func_mysqli_stmt_bind_result($link, $engine, "d", "MEDIUMINT UNSIGNED", NULL, 360); 164 165 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? max(-1 * PHP_INT_MAX + 1, -2147483648) : 1, 380); 166 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", -2147483647, 400, "integer"); 167 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", (defined("PHP_INT_MAX")) ? min(2147483647, PHP_INT_MAX) : 1, 420); 168 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER", NULL, 440); 169 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", (defined("PHP_INT_MAX")) ? min(4294967295, 2147483647) : 1, 460); 170 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", 4294967295, 480, (defined("PHP_INT_MAX") && (4294967295 > PHP_INT_MAX)) ? "string" : null); 171 func_mysqli_stmt_bind_result($link, $engine, "i", "INTEGER UNSIGNED", NULL, 500); 172 173 /* test is broken too: we bind "integer" but value is a float 174 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -9223372036854775808, 520); 175 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 18446744073709551615, 560); 176 */ 177 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", NULL, 540); 178 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", NULL, 580); 179 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1, 1780); 180 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", 1, 1800); 181 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT", -1 * PHP_INT_MAX + 1, 1820); 182 func_mysqli_stmt_bind_result($link, $engine, "i", "BIGINT UNSIGNED", PHP_INT_MAX, 1840); 183 184 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", -9237.21, 600); 185 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT", NULL, 620); 186 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED", 18467.5, 640); 187 func_mysqli_stmt_bind_result($link, $engine, "d", "FLOAT UNSIGNED ", NULL, 660); 188 189 // Yes, we need the temporary variable. The PHP casting will foul us otherwise. 190 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", '-99999999.99', 680, "double"); 191 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2)", NULL, 700); 192 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", '99999999.99' , 720, "double"); 193 func_mysqli_stmt_bind_result($link, $engine, "d", "DOUBLE(10,2) UNSIGNED", NULL, 740); 194 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", '-99999999.99', 760, "string"); 195 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 780); 196 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", '99999999.99', 800, "string"); 197 func_mysqli_stmt_bind_result($link, $engine, "d", "DECIMAL(10,2)", NULL, 820); 198 199 // don't care about date() strict TZ warnings... 200 func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", @date('Y-m-d'), 840); 201 func_mysqli_stmt_bind_result($link, $engine, "s", "DATE NOT NULL", @date('Y-m-d'), 860); 202 func_mysqli_stmt_bind_result($link, $engine, "s", "DATE", NULL, 880); 203 204 func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", @date('Y-m-d H:i:s'), 900); 205 func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME NOT NULL", @date('Y-m-d H:i:s'), 920); 206 func_mysqli_stmt_bind_result($link, $engine, "s", "DATETIME", NULL, 940); 207 208 func_mysqli_stmt_bind_result($link, $engine, "s", "TIMESTAMP", @date('Y-m-d H:i:s'), 960); 209 210 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", @date('H:i:s'), 980); 211 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME NOT NULL", @date('H:i:s'), 1000); 212 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME", NULL, 1020); 213 214 $tmp = intval(@date('Y')); 215 func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", $tmp, 1040, "string"); // YEAR is a string with implicit display width of 4 216 func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR NOT NULL", $tmp, 1060, "string"); 217 func_mysqli_stmt_bind_result($link, $engine, "s", "YEAR", NULL, 1080); 218 219 $string255 = func_mysqli_stmt_bind_make_string(255); 220 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", "a", 1110, 'string'); 221 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(255)", $string255, 1120, 'string'); 222 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1) NOT NULL", "a", 1140, 'string'); 223 func_mysqli_stmt_bind_result($link, $engine, "s", "CHAR(1)", NULL, 1160); 224 225 $string65k = func_mysqli_stmt_bind_make_string(65535); 226 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", "a", 1180, 'string'); 227 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(255)", $string255, 1200, 'string'); 228 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(65635)", $string65k, 1220, 'string'); 229 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1) NOT NULL", "a", 1240, 'string'); 230 func_mysqli_stmt_bind_result($link, $engine, "s", "VARCHAR(1)", NULL, 1260); 231 232 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", "a", 1280); 233 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", chr(0), 1300); 234 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1) NOT NULL", "b", 1320); 235 func_mysqli_stmt_bind_result($link, $engine, "s", "BINARY(1)", NULL, 1340); 236 237 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", "a", 1360); 238 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", chr(0), 1380); 239 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1) NOT NULL", "b", 1400); 240 func_mysqli_stmt_bind_result($link, $engine, "s", "VARBINARY(1)", NULL, 1420); 241 242 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", "a", 1440); 243 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", chr(0), 1460); 244 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB NOT NULL", "b", 1480); 245 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYBLOB", NULL, 1500); 246 247 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", "a", 1520, 'string'); 248 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT NOT NULL", "a", 1540, 'string'); 249 func_mysqli_stmt_bind_result($link, $engine, "s", "TINYTEXT", NULL, 1560, 'string'); 250 251 // Note: you cannot insert any blob values this way. But you can check the API at least partly this way 252 // Extra BLOB tests are in mysqli_stmt_send_long() 253 func_mysqli_stmt_bind_result($link, $engine, "b", "BLOB", "", 1580); 254 func_mysqli_stmt_bind_result($link, $engine, "b", "TEXT", "", 1600, 'string'); 255 func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMBLOB", "", 1620); 256 func_mysqli_stmt_bind_result($link, $engine, "b", "MEDIUMTEXT", "", 1640, 'string'); 257 258 /* Is this one related? http://bugs.php.net/bug.php?id=35759 */ 259 func_mysqli_stmt_bind_result($link, $engine, "b", "LONGBLOB", "", 1660); 260 func_mysqli_stmt_bind_result($link, $engine, "b", "LONGTEXT", "", 1680, 'string'); 261 262 func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", "a", 1700, 'string'); 263 func_mysqli_stmt_bind_result($link, $engine, "s", "ENUM('a', 'b')", NULL, 1720, 'string'); 264 func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", "a", 1740, 'string'); 265 func_mysqli_stmt_bind_result($link, $engine, "s", "SET('a', 'b')", NULL, 1760, 'string'); 266 267 if (mysqli_get_server_version($link) >= 50600) 268 func_mysqli_stmt_bind_result($link, $engine, "s", "TIME(6)", "13:31:34.123456", 1770); 269 270 $stmt = mysqli_stmt_init($link); 271 if (!mysqli_stmt_prepare($stmt, "INSERT INTO test(id, label) VALUES (1000, 'z')")) 272 printf("[3001] [%d] %s\n", mysqli_stmt_errno($stmt), mysqli_stmt_error($stmt)); 273 274 $id = null; 275 try { 276 mysqli_stmt_bind_result($stmt, $id); 277 } catch (\ArgumentCountError $e) { 278 echo $e->getMessage() . \PHP_EOL; 279 } 280 281 mysqli_stmt_close($stmt); 282 283 mysqli_close($link); 284 print "done!"; 285?> 286--CLEAN-- 287<?php 288 require_once 'clean_table.inc'; 289?> 290--EXPECTF-- 291mysqli_stmt object is not fully initialized 292Number of bind variables doesn't match number of fields in prepared statement 293Number of bind variables doesn't match number of fields in prepared statement 294int(1) 295%s(1) "a" 296Number of bind variables doesn't match number of fields in prepared statement 297done! 298