1--TEST-- 2MySQL PDO->prepare(), emulated PS 3--EXTENSIONS-- 4pdo_mysql 5--SKIPIF-- 6<?php 7require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 8MySQLPDOTest::skip(); 9?> 10--FILE-- 11<?php 12 require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 13 $db = MySQLPDOTest::factory(); 14 $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); 15 16 function prepex($offset, &$db, $query, $input_params = null, $error_info = null) { 17 try { 18 if (is_array($error_info) && isset($error_info['prepare'])) 19 $stmt = @$db->prepare($query); 20 else 21 $stmt = $db->prepare($query); 22 23 if (is_array($error_info) && isset($error_info['prepare'])) { 24 $tmp = $db->errorInfo(); 25 26 if (isset($error_info['prepare']['sqlstate']) && 27 ($error_info['prepare']['sqlstate'] !== $tmp[0])) { 28 printf("[%03d] prepare() - expecting SQLSTATE '%s' got '%s'\n", 29 $offset, $error_info['prepare']['sqlstate'], $tmp[0]); 30 return false; 31 } 32 33 if (isset($error_info['prepare']['mysql']) && 34 ($error_info['prepare']['mysql'] !== $tmp[1])) { 35 printf("[%03d] prepare() - expecting MySQL Code '%s' got '%s'\n", 36 $offset, $error_info['prepare']['mysql'], $tmp[0]); 37 return false; 38 } 39 40 return false; 41 } 42 43 if (is_null($input_params)) 44 $input_params = []; 45 46 if (is_array($error_info) && isset($error_info['execute'])) 47 $ret = @$stmt->execute($input_params); 48 else 49 $ret = $stmt->execute($input_params); 50 51 if (!is_bool($ret)) 52 printf("[%03d] PDO::execute() should return a boolean value, got %s/%s\n", 53 var_export($ret, true), $ret); 54 55 if (is_array($error_info) && isset($error_info['execute'])) { 56 $tmp = $stmt->errorInfo(); 57 58 if (isset($error_info['execute']['sqlstate']) && 59 ($error_info['execute']['sqlstate'] !== $tmp[0])) { 60 printf("[%03d] execute() - expecting SQLSTATE '%s' got '%s'\n", 61 $offset, $error_info['execute']['sqlstate'], $tmp[0]); 62 return false; 63 } 64 65 if (isset($error_info['execute']['mysql']) && 66 ($error_info['execute']['mysql'] !== $tmp[1])) { 67 printf("[%03d] execute() - expecting MySQL Code '%s' got '%s'\n", 68 $offset, $error_info['execute']['mysql'], $tmp[0]); 69 return false; 70 } 71 72 return false; 73 } 74 75 } catch (PDOException $e) { 76 printf("[%03d] %s, [%s} %s\n", 77 $offset, $e->getMessage(), 78 $db->errorCode(), implode(' ', $db->errorInfo())); 79 return false; 80 } 81 82 return $stmt; 83 } 84 85 try { 86 $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); 87 if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) 88 printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); 89 90 try { 91 prepex(3, $db, '', [], ['execute' => ['sqlstate' => '42000']]); 92 } catch (\ValueError $e) { 93 echo $e->getMessage(), \PHP_EOL; 94 } 95 96 prepex(4, $db, sprintf('CREATE TABLE test_prepare_emulated_anonymous_placeholder(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); 97 prepex(5, $db, "INSERT INTO test_prepare_emulated_anonymous_placeholder(id, label) VALUES(1, '?')"); 98 $stmt = prepex(6, $db, 'SELECT label FROM test_prepare_emulated_anonymous_placeholder'); 99 var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); 100 101 prepex(7, $db, 'DELETE FROM test_prepare_emulated_anonymous_placeholder'); 102 prepex(8, $db, "INSERT INTO test_prepare_emulated_anonymous_placeholder(id, label) VALUES(1, '?')", 103 array('first row')); 104 $stmt = prepex(9, $db, 'SELECT label FROM test_prepare_emulated_anonymous_placeholder'); 105 106 var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); 107 prepex(10, $db, 'DELETE FROM test_prepare_emulated_anonymous_placeholder'); 108 prepex(11, $db, 'INSERT INTO test_prepare_emulated_anonymous_placeholder(id, label) VALUES(1, ?)', 109 array('first row')); 110 prepex(12, $db, 'INSERT INTO test_prepare_emulated_anonymous_placeholder(id, label) VALUES(2, ?)', 111 array('second row')); 112 $stmt = prepex(13, $db, 'SELECT label FROM test_prepare_emulated_anonymous_placeholder'); 113 var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); 114 115 // Is PDO fun? 116 prepex(14, $db, 'SELECT label FROM test_prepare_emulated_anonymous_placeholder WHERE ? > 1', 117 array('id')); 118 prepex(15, $db, 'SELECT ? FROM test_prepare_emulated_anonymous_placeholder WHERE id > 1', 119 array('id')); 120 prepex(16, $db, 'SELECT ? FROM test_prepare_emulated_anonymous_placeholder WHERE ? > ?', 121 array('test'), array('execute' => array('sqlstate' => 'HY093'))); 122 123 prepex(17, $db, 'SELECT ? FROM test_prepare_emulated_anonymous_placeholder WHERE ? > ?', 124 array('id', 'label', 'value')); 125 126 for ($num_params = 2; $num_params < 100; $num_params++) { 127 $params = array('a'); 128 for ($i = 1; $i < $num_params; $i++) { 129 $params[] = 'some data'; 130 } 131 prepex(18, $db, 'SELECT id, label FROM test_prepare_emulated_anonymous_placeholder WHERE label > ?', 132 $params, array('execute' => array('sqlstate' => 'HY093'))); 133 } 134 135 prepex(19, $db, 'DELETE FROM test_prepare_emulated_anonymous_placeholder'); 136 prepex(20, $db, 'INSERT INTO test_prepare_emulated_anonymous_placeholder(id, label) VALUES (1, ?), (2, ?)', 137 array('row', 'row')); 138 $stmt = prepex(21, $db, 'SELECT id, label FROM test_prepare_emulated_anonymous_placeholder'); 139 var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); 140 141 $stmt = prepex(22, $db, 'SELECT id, label FROM test_prepare_emulated_anonymous_placeholder WHERE ? IS NOT NULL', 142 array(1)); 143 if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) 144 printf("[065] '1' IS NOT NULL evaluates to true, expecting two rows, got %d rows\n", $tmp); 145 146 $stmt = prepex(23, $db, 'SELECT id, label FROM test_prepare_emulated_anonymous_placeholder WHERE ? IS NULL', 147 array(1)); 148 if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) 149 printf("[067] '1' IS NOT NULL evaluates to true, expecting zero rows, got %d rows\n", $tmp); 150 } catch (PDOException $e) { 151 printf("[001] %s [%s] %s\n", 152 $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); 153 } 154 155 print "done!"; 156?> 157--CLEAN-- 158<?php 159require_once __DIR__ . '/inc/mysql_pdo_test.inc'; 160$db = MySQLPDOTest::factory(); 161$db->query('DROP TABLE IF EXISTS test_prepare_emulated_anonymous_placeholder'); 162?> 163--EXPECTF-- 164PDO::prepare(): Argument #1 ($query) cannot be empty 165array(1) { 166 [0]=> 167 array(1) { 168 ["label"]=> 169 string(1) "?" 170 } 171} 172 173Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in %s on line %d 174array(0) { 175} 176array(2) { 177 [0]=> 178 array(1) { 179 ["label"]=> 180 string(9) "first row" 181 } 182 [1]=> 183 array(1) { 184 ["label"]=> 185 string(10) "second row" 186 } 187} 188array(2) { 189 [0]=> 190 array(2) { 191 ["id"]=> 192 string(1) "1" 193 ["label"]=> 194 string(3) "row" 195 } 196 [1]=> 197 array(2) { 198 ["id"]=> 199 string(1) "2" 200 ["label"]=> 201 string(3) "row" 202 } 203} 204done! 205