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