mysqli_fetch_field_flags.phpt 8.3 KB

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