1--TEST-- 2MySQL: PDOStatement->getColumnMeta() 3--SKIPIF-- 4<?php # vim:ft=php 5require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc'); 6require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); 7MySQLPDOTest::skip(); 8// Too many differences among MySQL version - run only with a recent one 9$db = MySQLPDOTest::factory(); 10$stmt = $db->query('SELECT VERSION() as _version'); 11$row = $stmt->fetch(PDO::FETCH_ASSOC); 12$version = ((int)substr($row['_version'], 0, 1) * 10) + (int)substr($row['_version'], 2, 1); 13if ($version < 51) 14 die("skip Test needs MySQL 5.1+"); 15?> 16--FILE-- 17<?php 18require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); 19$db = MySQLPDOTest::factory(); 20$db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); 21MySQLPDOTest::createTestTable($db); 22 23try { 24 25 $stmt = $db->prepare('SELECT id FROM test ORDER BY id ASC'); 26 27 // execute() has not been called yet 28 // NOTE: no warning 29 if (false !== ($tmp = $stmt->getColumnMeta(0))) 30 printf("[002] Expecting false got %s\n", var_export($tmp, true)); 31 32 $stmt->execute(); 33 // Warning: PDOStatement::getColumnMeta() expects exactly 1 parameter, 0 given in 34 if (false !== ($tmp = @$stmt->getColumnMeta())) 35 printf("[003] Expecting false got %s\n", var_export($tmp, true)); 36 37 // invalid offset 38 if (false !== ($tmp = @$stmt->getColumnMeta(-1))) 39 printf("[004] Expecting false got %s\n", var_export($tmp, true)); 40 41 // Warning: PDOStatement::getColumnMeta() expects parameter 1 to be long, array given in 42 if (false !== ($tmp = @$stmt->getColumnMeta(array()))) 43 printf("[005] Expecting false got %s\n", var_export($tmp, true)); 44 45 // Warning: PDOStatement::getColumnMeta() expects exactly 1 parameter, 2 given in 46 if (false !== ($tmp = @$stmt->getColumnMeta(1, 1))) 47 printf("[006] Expecting false got %s\n", var_export($tmp, true)); 48 49 $emulated = $stmt->getColumnMeta(0); 50 51 printf("Testing native PS...\n"); 52 $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); 53 if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) 54 printf("[007] Unable to turn off emulated prepared statements\n"); 55 56 $stmt = $db->prepare('SELECT id FROM test ORDER BY id ASC'); 57 $stmt->execute(); 58 $native = $stmt->getColumnMeta(0); 59 if (count($native) == 0) { 60 printf("[008] Meta data seems wrong, %s / %s\n", 61 var_export($native, true), var_export($emulated, true)); 62 } 63 64 // invalid offset 65 if (false !== ($tmp = $stmt->getColumnMeta(1))) 66 printf("[009] Expecting false because of invalid offset got %s\n", var_export($tmp, true)); 67 68 69 function test_meta(&$db, $offset, $sql_type, $value, $native_type, $pdo_type) { 70 71 $db->exec('DROP TABLE IF EXISTS test'); 72 73 $sql = sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); 74 if (!($stmt = @$db->prepare($sql)) || (!@$stmt->execute())) { 75 // Some engines and/or MySQL server versions might not support the data type 76 return true; 77 } 78 79 if (!$db->exec(sprintf("INSERT INTO test(id, label) VALUES (1, '%s')", $value))) { 80 printf("[%03d] + 1] Insert failed, %d - %s\n", $offset, 81 $db->errorCode(), var_export($db->errorInfo(), true)); 82 return false; 83 } 84 85 $stmt = $db->prepare('SELECT id, label FROM test'); 86 $stmt->execute(); 87 $meta = $stmt->getColumnMeta(1); 88 $row = $stmt->fetch(PDO::FETCH_ASSOC); 89 90 if (empty($meta)) { 91 printf("[%03d + 2] getColumnMeta() failed, %d - %s\n", $offset, 92 $stmt->errorCode(), var_export($stmt->errorInfo(), true)); 93 return false; 94 } 95 96 $elements = array('flags', 'table', 'name', 'len', 'precision', 'pdo_type'); 97 foreach ($elements as $k => $element) 98 if (!isset($meta[$element])) { 99 printf("[%03d + 3] Element %s missing, %s\n", $offset, 100 $element, var_export($meta, true)); 101 return false; 102 } 103 104 if (($meta['table'] != 'test') || ($meta['name'] != 'label')) { 105 printf("[%03d + 4] Table or field name is wrong, %s\n", $offset, 106 var_export($meta, true)); 107 return false; 108 } 109 110 if (!is_null($native_type)) { 111 if (!isset($meta['native_type'])) { 112 printf("[%03d + 5] Element native_type missing, %s\n", $offset, 113 var_export($meta, true)); 114 return false; 115 } 116 117 if (!is_array($native_type)) 118 $native_type = array($native_type); 119 120 $found = false; 121 foreach ($native_type as $k => $type) { 122 if ($meta['native_type'] == $type) { 123 $found = true; 124 break; 125 } 126 } 127 128 if (!$found) { 129 printf("[%03d + 6] Expecting native type %s, %s\n", $offset, 130 var_export($native_type, true), var_export($meta, true)); 131 return false; 132 } 133 } 134 135 if (!is_null($pdo_type) && ($meta['pdo_type'] != $pdo_type)) { 136 printf("[%03d + 6] Expecting PDO type %s got %s (%s)\n", $offset, 137 $pdo_type, var_export($meta, true), var_export($meta['native_type'])); 138 return false; 139 } 140 141 return true; 142 } 143 144 $stmt = $db->prepare('SELECT @@sql_mode AS _mode'); 145 $stmt->execute(); 146 $row = $stmt->fetch(PDO::FETCH_ASSOC); 147 $real_as_float = (false === stristr($row['_mode'], "REAL_AS_FLOAT")) ? false : true; 148 149 $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); 150 $is_mysqlnd = MySQLPDOTest::isPDOMySQLnd(); 151 test_meta($db, 20, 'BIT(8)', 1, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 152 test_meta($db, 30, 'TINYINT', -127, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 153 test_meta($db, 40, 'TINYINT UNSIGNED', 255, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 154 test_meta($db, 50, 'BOOLEAN', 1, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 155 156 test_meta($db, 60, 'SMALLINT', -32768, 'SHORT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 157 test_meta($db, 70, 'SMALLINT UNSIGNED', 65535, 'SHORT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 158 159 test_meta($db, 80, 'MEDIUMINT', -8388608, 'INT24', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 160 test_meta($db, 90, 'MEDIUMINT UNSIGNED', 16777215, 'INT24', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 161 162 test_meta($db, 100, 'INT', -2147483648, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 163 test_meta($db, 110, 'INT UNSIGNED', 4294967295, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 164 165 test_meta($db, 120, 'BIGINT', -9223372036854775808, 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR); 166 test_meta($db, 130, 'BIGINT UNSIGNED', 18446744073709551615, 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR); 167 168 test_meta($db, 130, 'REAL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); 169 test_meta($db, 140, 'REAL UNSIGNED', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); 170 test_meta($db, 150, 'REAL ZEROFILL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); 171 test_meta($db, 160, 'REAL UNSIGNED ZEROFILL', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); 172 173 test_meta($db, 170, 'DOUBLE', -1.01, 'DOUBLE', PDO::PARAM_STR); 174 test_meta($db, 180, 'DOUBLE UNSIGNED', 1.01, 'DOUBLE', PDO::PARAM_STR); 175 test_meta($db, 190, 'DOUBLE ZEROFILL', -1.01, 'DOUBLE', PDO::PARAM_STR); 176 test_meta($db, 200, 'DOUBLE UNSIGNED ZEROFILL', 1.01, 'DOUBLE', PDO::PARAM_STR); 177 178 test_meta($db, 210, 'FLOAT', -1.01, 'FLOAT', PDO::PARAM_STR); 179 test_meta($db, 220, 'FLOAT UNSIGNED', 1.01, 'FLOAT', PDO::PARAM_STR); 180 test_meta($db, 230, 'FLOAT ZEROFILL', -1.01, 'FLOAT', PDO::PARAM_STR); 181 test_meta($db, 240, 'FLOAT UNSIGNED ZEROFILL', 1.01, 'FLOAT', PDO::PARAM_STR); 182 183 test_meta($db, 250, 'DECIMAL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 184 test_meta($db, 260, 'DECIMAL UNSIGNED', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 185 test_meta($db, 270, 'DECIMAL ZEROFILL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 186 test_meta($db, 280, 'DECIMAL UNSIGNED ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 187 188 test_meta($db, 290, 'NUMERIC', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 189 test_meta($db, 300, 'NUMERIC UNSIGNED', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 190 test_meta($db, 310, 'NUMERIC ZEROFILL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 191 test_meta($db, 320, 'NUMERIC UNSIGNED ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); 192 193 test_meta($db, 330, 'DATE', '2008-04-23', array('DATE', 'NEWDATE'), PDO::PARAM_STR); 194 test_meta($db, 340, 'TIME', '14:37:00', 'TIME', PDO::PARAM_STR); 195 test_meta($db, 350, 'TIMESTAMP', time(), 'TIMESTAMP', PDO::PARAM_STR); 196 test_meta($db, 360, 'DATETIME', '2008-03-23 14:38:00', 'DATETIME', PDO::PARAM_STR); 197 test_meta($db, 370, 'YEAR', '2008', NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); 198 199 test_meta($db, 380, 'CHAR(1)', 'a', 'STRING', PDO::PARAM_STR); 200 test_meta($db, 390, 'CHAR(10)', '0123456789', 'STRING', PDO::PARAM_STR); 201 test_meta($db, 400, 'CHAR(255)', str_repeat('z', 255), 'STRING', PDO::PARAM_STR); 202 test_meta($db, 410, 'VARCHAR(1)', 'a', 'VAR_STRING', PDO::PARAM_STR); 203 test_meta($db, 420, 'VARCHAR(10)', '0123456789', 'VAR_STRING', PDO::PARAM_STR); 204 test_meta($db, 430, 'VARCHAR(255)', str_repeat('z', 255), 'VAR_STRING', PDO::PARAM_STR); 205 206 test_meta($db, 440, 'BINARY(1)', str_repeat('a', 1), 'STRING', PDO::PARAM_STR); 207 test_meta($db, 450, 'BINARY(255)', str_repeat('b', 255), 'STRING', PDO::PARAM_STR); 208 test_meta($db, 460, 'VARBINARY(1)', str_repeat('a', 1), 'VAR_STRING', PDO::PARAM_STR); 209 test_meta($db, 470, 'VARBINARY(255)', str_repeat('b', 255), 'VAR_STRING', PDO::PARAM_STR); 210 211 test_meta($db, 480, 'TINYBLOB', str_repeat('b', 255), 'BLOB', PDO::PARAM_STR); 212 test_meta($db, 490, 'BLOB', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 213 test_meta($db, 500, 'MEDIUMBLOB', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 214 test_meta($db, 510, 'LONGBLOB', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 215 216 test_meta($db, 520, 'TINYTEXT', str_repeat('b', 255), 'BLOB', PDO::PARAM_STR); 217 test_meta($db, 530, 'TINYTEXT BINARY', str_repeat('b', 255), 'BLOB', PDO::PARAM_STR); 218 219 test_meta($db, 560, 'TEXT', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 220 test_meta($db, 570, 'TEXT BINARY', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 221 222 test_meta($db, 580, 'MEDIUMTEXT', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 223 test_meta($db, 590, 'MEDIUMTEXT BINARY', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 224 225 test_meta($db, 600, 'LONGTEXT', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 226 test_meta($db, 610, 'LONGTEXT BINARY', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); 227 228 test_meta($db, 620, "ENUM('yes', 'no') DEFAULT 'yes'", 'no', NULL, PDO::PARAM_STR); 229 test_meta($db, 630, "SET('yes', 'no') DEFAULT 'yes'", 'no', NULL, PDO::PARAM_STR); 230 231/* 232 | spatial_type 233*/ 234 235 // unique key 236 $db->exec('DROP TABLE IF EXISTS test'); 237 $sql = sprintf('CREATE TABLE test(id INT, label INT UNIQUE) ENGINE = %s', MySQLPDOTest::getTableEngine()); 238 if (($stmt = @$db->prepare($sql)) && @$stmt->execute()) { 239 $db->exec('INSERT INTO test(id, label) VALUES (1, 2)'); 240 $stmt = $db->query('SELECT id, label FROM test'); 241 $meta = $stmt->getColumnMeta(1); 242 if (!isset($meta['flags'])) { 243 printf("[1000] No flags contained in metadata %s\n", var_export($meta, true)); 244 } else { 245 $flags = $meta['flags']; 246 $found = false; 247 foreach ($flags as $k => $flag) { 248 if ($flag == 'unique_key') 249 $found = true; 250 } 251 if (!$found) 252 printf("[1001] Flags seem wrong %s\n", var_export($meta, true)); 253 } 254 } 255 256 // primary key 257 $db->exec('DROP TABLE IF EXISTS test'); 258 $sql = sprintf('CREATE TABLE test(id INT PRIMARY KEY NOT NULL AUTO_INCREMENT) ENGINE = %s', MySQLPDOTest::getTableEngine()); 259 if (($stmt = @$db->prepare($sql)) && @$stmt->execute()) { 260 $db->exec('INSERT INTO test(id) VALUES (1)'); 261 $stmt = $db->query('SELECT id FROM test'); 262 $meta = $stmt->getColumnMeta(0); 263 if (!isset($meta['flags'])) { 264 printf("[1002] No flags contained in metadata %s\n", var_export($meta, true)); 265 } else { 266 $flags = $meta['flags']; 267 $found = false; 268 foreach ($flags as $k => $flag) { 269 if ($flag == 'primary_key') 270 $found = true; 271 } 272 if (!$found) 273 printf("[1003] Flags seem wrong %s\n", var_export($meta, true)); 274 } 275 } 276 277 // multiple key 278 $db->exec('DROP TABLE IF EXISTS test'); 279 $sql = sprintf('CREATE TABLE test(id INT, label1 INT, label2 INT, INDEX idx1(label1, label2)) ENGINE = %s', MySQLPDOTest::getTableEngine()); 280 if (($stmt = @$db->prepare($sql)) && @$stmt->execute()) { 281 $db->exec('INSERT INTO test(id, label1, label2) VALUES (1, 2, 3)'); 282 $stmt = $db->query('SELECT id, label1, label2 FROM test'); 283 $meta = $stmt->getColumnMeta(1); 284 if (!isset($meta['flags'])) { 285 printf("[1004] No flags contained in metadata %s\n", var_export($meta, true)); 286 } else { 287 $flags = $meta['flags']; 288 $found = false; 289 foreach ($flags as $k => $flag) { 290 if ($flag == 'multiple_key') 291 $found = true; 292 } 293 if (!$found) 294 printf("[1005] Flags seem wrong %s\n", var_export($meta, true)); 295 } 296 } 297 298 $stmt = $db->query('SELECT NULL AS col1'); 299 $meta = $stmt->getColumnMeta(0); 300 if ('NULL' !== $meta['native_type']) 301 printf("[1006] Expecting NULL got %s\n", $meta['native_type']); 302 303} catch (PDOException $e) { 304 // we should never get here, we use warnings, but never trust a system... 305 printf("[001] %s, [%s} %s\n", 306 $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo())); 307} 308 309$db->exec('DROP TABLE IF EXISTS test'); 310print "done!"; 311?> 312--EXPECTF-- 313Testing native PS... 314done!