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