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