1--TEST-- 2mysqli_stmt_attr_set() - mysqlnd does not check for invalid codes 3--EXTENSIONS-- 4mysqli 5--SKIPIF-- 6<?php 7require_once('skipifconnectfailure.inc'); 8?> 9--FILE-- 10<?php 11require_once("connect.inc"); 12 13 require('table.inc'); 14 15 $valid_attr = array(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH); 16 $valid_attr[] = MYSQLI_STMT_ATTR_CURSOR_TYPE; 17 $valid_attr[] = MYSQLI_CURSOR_TYPE_NO_CURSOR; 18 $valid_attr[] = MYSQLI_CURSOR_TYPE_READ_ONLY; 19 $valid_attr[] = MYSQLI_CURSOR_TYPE_FOR_UPDATE; 20 $valid_attr[] = MYSQLI_CURSOR_TYPE_SCROLLABLE; 21 $valid_attr[] = MYSQLI_STMT_ATTR_PREFETCH_ROWS; 22 23 24 $stmt = mysqli_stmt_init($link); 25 try { 26 mysqli_stmt_attr_set($stmt, 0, 0); 27 } catch (\Throwable $e) { 28 echo get_class($e) . ': ' . $e->getMessage() . PHP_EOL; 29 } 30 31 $stmt->prepare("SELECT * FROM test"); 32 // Invalid Attribute (2nd argument) 33 try { 34 mysqli_stmt_attr_set($stmt, -1, 0); 35 } catch (\ValueError $e) { 36 echo $e->getMessage() . \PHP_EOL; 37 } 38 // Invalid mode for MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH 39 try { 40 $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, -1); 41 } catch (\ValueError $e) { 42 echo $e->getMessage() . \PHP_EOL; 43 } 44 $stmt->close(); 45 46 // 47 // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH 48 // 49 // expecting max_length not to be set and be 0 in all cases 50 $stmt = mysqli_stmt_init($link); 51 $stmt->prepare("SELECT label FROM test"); 52 $stmt->execute(); 53 $stmt->store_result(); 54 $res = $stmt->result_metadata(); 55 $fields = $res->fetch_fields(); 56 $max_lengths = array(); 57 foreach ($fields as $k => $meta) { 58 $max_lengths[$meta->name] = $meta->max_length; 59 if ($meta->max_length !== 0) 60 printf("[007] max_length should be not set (= 0), got %s for field %s\n", $meta->max_length, $meta->name); 61 } 62 $res->close(); 63 $stmt->close(); 64 65 // MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH is no longer supported, expect no change in behavior. 66 $stmt = mysqli_stmt_init($link); 67 $stmt->prepare("SELECT label FROM test"); 68 var_dump($stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 1)); 69 $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH); 70 if ($res !== 1) 71 printf("[007.1] max_length should be 1, got %s\n", $res); 72 $stmt->execute(); 73 $stmt->store_result(); 74 $res = $stmt->result_metadata(); 75 $fields = $res->fetch_fields(); 76 $max_lengths = array(); 77 foreach ($fields as $k => $meta) { 78 $max_lengths[$meta->name] = $meta->max_length; 79 if ($meta->max_length !== 0) 80 printf("[008] max_length should be not set (= 0), got %s for field %s\n", $meta->max_length, $meta->name); 81 } 82 $res->close(); 83 $stmt->close(); 84 85 // expecting max_length not to be set 86 $stmt = mysqli_stmt_init($link); 87 $stmt->prepare("SELECT label FROM test"); 88 $stmt->attr_set(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, 0); 89 $res = $stmt->attr_get(MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH); 90 if ($res !== 0) 91 printf("[008.1] max_length should be 0, got %s\n", $res); 92 $stmt->execute(); 93 $stmt->store_result(); 94 $res = $stmt->result_metadata(); 95 $fields = $res->fetch_fields(); 96 $max_lengths = array(); 97 foreach ($fields as $k => $meta) { 98 $max_lengths[$meta->name] = $meta->max_length; 99 if ($meta->max_length !== 0) 100 printf("[009] max_length should not be set (= 0), got %s for field %s\n", $meta->max_length, $meta->name); 101 } 102 $res->close(); 103 $stmt->close(); 104 105 // 106 // Cursors 107 // 108 109 110 $stmt = mysqli_stmt_init($link); 111 $stmt->prepare("SELECT id, label FROM test"); 112 113 // Invalid cursor type 114 try { 115 $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, -1); 116 } catch (\ValueError $e) { 117 echo $e->getMessage() . \PHP_EOL; 118 } 119 120 if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_FOR_UPDATE))) 121 printf("[011] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); 122 123 if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_SCROLLABLE))) 124 printf("[012] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); 125 126 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR))) 127 printf("[013] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 128 129 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY))) 130 printf("[014] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 131 132 $stmt->close(); 133 134 $stmt = mysqli_stmt_init($link); 135 $stmt->prepare("SELECT id, label FROM test"); 136 $stmt->execute(); 137 $id = $label = NULL; 138 $stmt->bind_result($id, $label); 139 $results = array(); 140 while ($stmt->fetch()) 141 $results[$id] = $label; 142 $stmt->close(); 143 if (empty($results)) 144 printf("[015] Results should not be empty, subsequent tests will probably fail!\n"); 145 146 $stmt = mysqli_stmt_init($link); 147 $stmt->prepare("SELECT id, label FROM test"); 148 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_NO_CURSOR))) 149 printf("[016] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 150 $stmt->execute(); 151 $id = $label = NULL; 152 $stmt->bind_result($id, $label); 153 $results2 = array(); 154 while ($stmt->fetch()) 155 $results2[$id] = $label; 156 $stmt->close(); 157 if ($results != $results2) { 158 printf("[017] Results should not differ. Dumping both result sets.\n"); 159 var_dump($results); 160 var_dump($results2); 161 } 162 163 $stmt = mysqli_stmt_init($link); 164 $stmt->prepare("SELECT id, label FROM test"); 165 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_CURSOR_TYPE, MYSQLI_CURSOR_TYPE_READ_ONLY))) 166 printf("[018] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 167 $stmt->execute(); 168 $id = $label = NULL; 169 $stmt->bind_result($id, $label); 170 $results2 = array(); 171 while ($stmt->fetch()) 172 $results2[$id] = $label; 173 $stmt->close(); 174 if ($results != $results2) { 175 printf("[019] Results should not differ. Dumping both result sets.\n"); 176 var_dump($results); 177 var_dump($results2); 178 } 179 180 181 // 182 // MYSQLI_STMT_ATTR_PREFETCH_ROWS 183 // 184 185 $stmt = mysqli_stmt_init($link); 186 $stmt->prepare("SELECT id, label FROM test"); 187 // Invalid prefetch value 188 try { 189 $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 0); 190 } catch (\ValueError $e) { 191 echo $e->getMessage() . \PHP_EOL; 192 } 193 194 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 1))) 195 printf("[020] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 196 $stmt->execute(); 197 $id = $label = NULL; 198 $stmt->bind_result($id, $label); 199 $results = array(); 200 while ($stmt->fetch()) 201 $results[$id] = $label; 202 $stmt->close(); 203 if (empty($results)) 204 printf("[021] Results should not be empty, subsequent tests will probably fail!\n"); 205 206 /* prefetch is not supported 207 $stmt = mysqli_stmt_init($link); 208 $stmt->prepare("SELECT label FROM test"); 209 if (false !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, -1))) 210 printf("[022] Expecting boolean/false, got %s/%s\n", gettype($tmp), $tmp); 211 $stmt->close(); 212 213 $stmt = mysqli_stmt_init($link); 214 $stmt->prepare("SELECT label FROM test"); 215 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, PHP_INT_MAX))) 216 printf("[023] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 217 $stmt->close(); 218 219 $stmt = mysqli_stmt_init($link); 220 $stmt->prepare("SELECT id, label FROM test"); 221 if (true !== ($tmp = $stmt->attr_set(MYSQLI_STMT_ATTR_PREFETCH_ROWS, 2))) 222 printf("[024] Expecting boolean/true, got %s/%s\n", gettype($tmp), $tmp); 223 $stmt->execute(); 224 $id = $label = NULL; 225 $stmt->bind_result($id, $label); 226 $results2 = array(); 227 while ($stmt->fetch()) 228 $results2[$id] = $label; 229 $stmt->close(); 230 if ($results != $results2) { 231 printf("[025] Results should not differ. Dumping both result sets.\n"); 232 var_dump($results); 233 var_dump($results2); 234 } 235 */ 236 237 mysqli_close($link); 238 print "done!"; 239?> 240--CLEAN-- 241<?php 242 require_once("clean_table.inc"); 243?> 244--EXPECT-- 245Error: mysqli_stmt object is not fully initialized 246mysqli_stmt_attr_set(): Argument #2 ($attribute) must be one of MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH, MYSQLI_STMT_ATTR_PREFETCH_ROWS, or STMT_ATTR_CURSOR_TYPE 247mysqli_stmt::attr_set(): Argument #2 ($value) must be 0 or 1 for attribute MYSQLI_STMT_ATTR_UPDATE_MAX_LENGTH 248bool(true) 249mysqli_stmt::attr_set(): Argument #2 ($value) must be one of the MYSQLI_CURSOR_TYPE_* constants for attribute MYSQLI_STMT_ATTR_CURSOR_TYPE 250mysqli_stmt::attr_set(): Argument #2 ($value) must be greater than 0 for attribute MYSQLI_STMT_ATTR_PREFETCH_ROWS 251done! 252