1--TEST-- 2mysqli_fetch_field() - flags/field->flags 3--EXTENSIONS-- 4mysqli 5--SKIPIF-- 6<?php 7require_once 'connect.inc'; 8if (!$link = @my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) 9 die(sprintf("skip Can't connect to MySQL Server - [%d] %s", mysqli_connect_errno(), mysqli_connect_error())); 10 11if (mysqli_get_server_version($link) < 50041) 12 die("skip: Due to many MySQL Server differences, the test requires 5.0.41+"); 13 14mysqli_close($link); 15?> 16--FILE-- 17<?php 18 require_once 'connect.inc'; 19 20/* TODO: mysqli.c needs to export a few more constants - see all the defined() calls! */ 21 22 $flags = array( 23 MYSQLI_NOT_NULL_FLAG => 'NOT_NULL', 24 MYSQLI_PRI_KEY_FLAG => 'PRI_KEY', 25 MYSQLI_UNIQUE_KEY_FLAG => 'UNIQUE_KEY', 26 MYSQLI_MULTIPLE_KEY_FLAG => 'MULTIPLE_KEY', 27 MYSQLI_BLOB_FLAG => 'BLOB', 28 MYSQLI_UNSIGNED_FLAG => 'UNSIGNED', 29 MYSQLI_ZEROFILL_FLAG => 'ZEROFILL', 30 MYSQLI_AUTO_INCREMENT_FLAG => 'AUTO_INCREMENT', 31 MYSQLI_TIMESTAMP_FLAG => 'TIMESTAMP', 32 MYSQLI_SET_FLAG => 'SET', 33 MYSQLI_NUM_FLAG => 'NUM', 34 MYSQLI_PART_KEY_FLAG => 'PART_KEY', 35 // MYSQLI_GROUP_FLAG => 'MYSQLI_GROUP_FLAG' - internal usage only 36 (defined('MYSQLI_NO_DEFAULT_VALUE_FLAG') ? MYSQLI_NO_DEFAULT_VALUE_FLAG : 4096) => 'NO_DEFAULT_VALUE', 37 (defined('MYSQLI_BINARY_FLAG') ? MYSQLI_BINARY_FLAG : 128) => 'BINARY', 38 (defined('MYSQLI_ENUM_FLAG') ? MYSQLI_ENUM_FLAG : 256) => 'ENUM', 39 // MYSQLI_BINCMP_FLAG 40 ); 41 42 // 5.1.24 / 6.0.4+ 43 if (defined('MYSQLI_ON_UPDATE_NOW')) 44 $flags[MYSQLI_ON_UPDATE_NOW] = 'ON_UPDATE_NOW'; 45 else 46 $flags[8192] = 'ON_UPDATE_NOW'; 47 48 krsort($flags); 49 50 $columns = array( 51 'INT DEFAULT NULL' => 'NUM', 52 'INT NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE NUM', 53 'INT NOT NULL DEFAULT 1' => 'NOT_NULL NUM', 54 'INT UNSIGNED DEFAULT NULL' => 'UNSIGNED NUM', 55 'INT UNSIGNED NOT NULL' => 'NOT_NULL UNSIGNED NO_DEFAULT_VALUE NUM', 56 'INT UNSIGNED NOT NULL DEFAULT 1' => 'NOT_NULL UNSIGNED NUM', 57 'INT UNSIGNED ZEROFILL DEFAULT NULL' => 'UNSIGNED ZEROFILL NUM', 58 'INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY' => 'NOT_NULL PRI_KEY UNSIGNED AUTO_INCREMENT NUM PART_KEY', 59 'CHAR(1) DEFAULT NULL' => '', 60 'CHAR(1) NOT NULL' => 'NOT_NULL NO_DEFAULT_VALUE', 61 'VARBINARY(127) DEFAULT NULL' => 'BINARY', 62 'BLOB' => 'BLOB BINARY', 63 'TINYBLOB' => 'BLOB BINARY', 64 'MEDIUMBLOB' => 'BLOB BINARY', 65 'LONGBLOB' => 'BLOB BINARY', 66 'TEXT' => 'BLOB', 67 'TINYTEXT' => 'BLOB', 68 'MEDIUMTEXT' => 'BLOB', 69 'LONGTEXT' => 'BLOB', 70 'SET("one", "two")' => 'SET', 71 'SET("one", "two") NOT NULL' => 'NOT_NULL SET NO_DEFAULT_VALUE', 72 'SET("one", "two") NOT NULL DEFAULT "one"' => 'NOT_NULL SET', 73 'ENUM("one", "two")' => 'ENUM', 74 'ENUM("one", "two") NOT NULL' => 'NOT_NULL ENUM NO_DEFAULT_VALUE', 75 'ENUM("one", "two") NOT NULL DEFAULT "one"' => 'NOT_NULL ENUM', 76 'TINYINT UNIQUE' => 'UNIQUE_KEY NUM PART_KEY', 77 'SMALLINT UNIQUE' => 'UNIQUE_KEY NUM PART_KEY', 78 'MEDIUMINT UNIQUE DEFAULT 1' => 'UNIQUE_KEY NUM PART_KEY', 79 'BIGINT UNSIGNED UNIQUE DEFAULT 100' => 'UNIQUE_KEY UNSIGNED NUM PART_KEY', 80 'BIT' => 'UNSIGNED', 81 'VARCHAR(2) NOT NULL PRIMARY KEY' => 'NOT_NULL PRI_KEY NO_DEFAULT_VALUE PART_KEY' 82 ); 83 84 85 86 function checkFlags($reported_flags, $expected_flags, $flags) { 87 $found_flags = $unexpected_flags = ''; 88 foreach ($flags as $code => $name) { 89 if ($reported_flags >= $code) { 90 $reported_flags -= $code; 91 $found_flags .= $name . ' '; 92 if (stristr($expected_flags, $name)) { 93 $expected_flags = trim(str_ireplace($name, '', $expected_flags)); 94 } else { 95 $unexpected_flags .= $name . ' '; 96 } 97 } 98 } 99 100 return array($expected_flags, $unexpected_flags, $found_flags); 101 } 102 103 if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) 104 printf("[001] [%d] %s\n", mysqli_connect_errno(), mysqli_connect_error()); 105 106 foreach ($columns as $column_def => $expected_flags) { 107 if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) { 108 printf("[002] %s [%d] %s\n", $column_def, 109 mysqli_errno($link), mysqli_error($link)); 110 continue; 111 } 112 113 $create = sprintf('CREATE TABLE test(id INT, col1 %s)', $column_def); 114 if (!mysqli_query($link, $create)) { 115 // Server might not support it - skip 116 continue; 117 } 118 119 if (!$res = mysqli_query($link, 'SELECT * FROM test')) { 120 printf("[003] Can't select from table, %s [%d] %s\n", $column_def, 121 mysqli_errno($link), mysqli_error($link)); 122 continue; 123 } 124 125 $field = mysqli_fetch_field_direct($res, 1); 126 if (!is_object($field)) { 127 printf("[004] Fetching the meta data failed, %s [%d] %s\n", $column_def, 128 mysqli_errno($link), mysqli_error($link)); 129 continue; 130 } 131 if ($field->name != 'col1') { 132 printf("[005] Field information seems wrong, %s [%d] %s\n", $column_def, 133 mysqli_errno($link), mysqli_error($link)); 134 continue; 135 } 136 137 /* 138 TODO 139 Unfortunately different server versions give you slightly different 140 results.The test does not yet fully reflect all server changes/bugs etc. 141 */ 142 switch ($column_def) { 143 case 'INT UNSIGNED NOT NULL': 144 case 'INT NOT NULL': 145 case 'CHAR(1) NOT NULL': 146 case 'SET("one", "two") NOT NULL': 147 case 'ENUM("one", "two") NOT NULL': 148 $version = mysqli_get_server_version($link); 149 if ($version < 50000) { 150 // TODO - check exact version! 151 $expected_flags = trim(str_replace('NO_DEFAULT_VALUE', '', $expected_flags)); 152 } 153 break; 154 155 case 'BIT': 156 $version = mysqli_get_server_version($link); 157 if (($version <= 50114 && $version > 50100) || ($version == 50200)) { 158 // TODO - check exact version! 159 $expected_flags = trim(str_replace('UNSIGNED', '', $expected_flags)); 160 } 161 162 default: 163 break; 164 } 165 166 list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags, $flags); 167 if ($unexpected_flags) { 168 printf("[006] Found unexpected flags '%s' for %s, found '%s' with MySQL %s'\n", 169 $unexpected_flags, $column_def, $flags_found, mysqli_get_server_version($link)); 170 } 171 if ($missing_flags) { 172 printf("[007] The flags '%s' have not been reported for %s, found '%s'\n", 173 $missing_flags, $column_def, $flags_found); 174 var_dump($create); 175 var_dump(mysqli_get_server_version($link)); 176 die($missing_flags); 177 } 178 179 mysqli_free_result($res); 180 } 181 182 if (!mysqli_query($link, 'DROP TABLE IF EXISTS test')) { 183 printf("[008] %s [%d] %s\n", $column_def, 184 mysqli_errno($link), mysqli_error($link)); 185 } 186 187 $column_def = array('col1 CHAR(1)', 'col2 CHAR(2)','INDEX idx_col1_col2(col1, col2)'); 188 $expected_flags = array('col1' => 'MULTIPLE_KEY PART_KEY', 'col2' => 'PART_KEY'); 189 $create = 'CREATE TABLE test(id INT, '; 190 foreach ($column_def as $k => $v) { 191 $create .= sprintf('%s, ', $v); 192 } 193 $create = sprintf('%s)', substr($create, 0, -2)); 194 195 if (mysqli_query($link, $create)) { 196 if (!$res = mysqli_query($link, 'SELECT * FROM test')) { 197 printf("[009] Cannot run SELECT, [%d] %s\n", 198 mysqli_errno($link), mysqli_error($link)); 199 } 200 // id column - skip it 201 $field = mysqli_fetch_field($res); 202 while ($field = mysqli_fetch_field($res)) { 203 if (!isset($expected_flags[$field->name])) { 204 printf("[010] Found unexpected field '%s'\n", $field->name); 205 } 206 list($missing_flags, $unexpected_flags, $flags_found) = checkFlags($field->flags, $expected_flags[$field->name], $flags); 207 if ($unexpected_flags) 208 printf("[011] Found unexpected flags '%s' for %s, found '%s'\n", 209 $unexpected_flags, $field->name, $flags_found); 210 if ($missing_flags) 211 printf("[012] The flags '%s' have not been reported for %s, found '%s'\n", 212 $missing_flags, $field->name, $flags_found); 213 } 214 } 215 216 mysqli_close($link); 217 print "done!"; 218?> 219--CLEAN-- 220<?php 221require_once 'clean_table.inc'; 222?> 223--EXPECT-- 224done! 225