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