diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug41125.php b/hphp/test/zend/bad/ext-pdo_mysql/bug41125.php new file mode 100644 index 000000000..396fb489a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug41125.php @@ -0,0 +1,75 @@ +quote('%' . $search . '%'); +$stmt = $db->prepare($sql); +$stmt->execute(); +print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; +print implode(' - ', $stmt->errorinfo()) ."\n"; + +print "-------------------------------------------------------\n"; + +$queries = array( + "SELECT 1 FROM DUAL WHERE 1 = '?\'\''", + "SELECT 'a\\'0' FROM DUAL WHERE 1 = ?", + "SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\\'' AND ?", + "SELECT 'foo?bar', '', '''' FROM DUAL WHERE ?" +); + +foreach ($queries as $k => $query) { + $stmt = $db->prepare($query); + $stmt->execute(array(1)); + printf("[%d] Query: [[%s]]\n", $k + 1, $query); + print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; + print implode(' - ', $stmt->errorinfo()) ."\n"; + print "--------\n"; +} + +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +$sql = "SELECT upper(:id) FROM DUAL WHERE '1'"; +$stmt = $db->prepare($sql); + +$id = 'o\'\0'; +$stmt->bindParam(':id', $id); +$stmt->execute(); +printf("Query: [[%s]]\n", $sql); +print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; +print implode(' - ', $stmt->errorinfo()) ."\n"; + +print "-------------------------------------------------------\n"; + +$queries = array( + "SELECT 1, 'foo' FROM DUAL WHERE 1 = :id AND '\\0' IS NULL AND 2 <> :id", + "SELECT 1 FROM DUAL WHERE 1 = :id AND '' AND 2 <> :id", + "SELECT 1 FROM DUAL WHERE 1 = :id AND '\'\'' = '''' AND 2 <> :id", + "SELECT 1 FROM DUAL WHERE 1 = :id AND '\'' = '''' AND 2 <> :id", + "SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\\'' AND 1", + "SELECT 'a''', '\'b\'' FROM DUAL WHERE '''' LIKE '\\'' AND 1", + "SELECT UPPER(:id) FROM DUAL WHERE '1'", + "SELECT 1 FROM DUAL WHERE '\''", + "SELECT 1 FROM DUAL WHERE :id AND '\\0' OR :id", + "SELECT 1 FROM DUAL WHERE 'a\\f\\n\\0' AND 1 >= :id", + "SELECT 1 FROM DUAL WHERE '\'' = ''''", + "SELECT '\\n' '1 FROM DUAL WHERE '''' and :id'", + "SELECT 1 'FROM DUAL WHERE :id AND '''' = '''' OR 1 = 1 AND ':id", +); + +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +$id = 1; + +foreach ($queries as $k => $query) { + $stmt = $db->prepare($query); + $stmt->bindParam(':id', $id); + $stmt->execute(); + + printf("[%d] Query: [[%s]]\n", $k + 1, $query); + print implode(' - ', (($r = @$stmt->fetch(PDO::FETCH_NUM)) ? $r : array())) ."\n"; + print implode(' - ', $stmt->errorinfo()) ."\n"; + print "--------\n"; +} + +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug41125.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug41125.php.expectf new file mode 100644 index 000000000..82a5896cc --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug41125.php.expectf @@ -0,0 +1,76 @@ +1 +00000 - - +------------------------------------------------------- +[1] Query: [[SELECT 1 FROM DUAL WHERE 1 = '?\'\'']] + +00000 - - +-------- +[2] Query: [[SELECT 'a\'0' FROM DUAL WHERE 1 = ?]] +a'0 +00000 - - +-------- +[3] Query: [[SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\'' AND ?]] +a - b' +00000 - - +-------- +[4] Query: [[SELECT 'foo?bar', '', '''' FROM DUAL WHERE ?]] +foo?bar - - ' +00000 - - +-------- +Query: [[SELECT upper(:id) FROM DUAL WHERE '1']] +O'\0 +00000 - - +------------------------------------------------------- +[1] Query: [[SELECT 1, 'foo' FROM DUAL WHERE 1 = :id AND '\0' IS NULL AND 2 <> :id]] + +00000 - - +-------- +[2] Query: [[SELECT 1 FROM DUAL WHERE 1 = :id AND '' AND 2 <> :id]] + +00000 - - +-------- +[3] Query: [[SELECT 1 FROM DUAL WHERE 1 = :id AND '\'\'' = '''' AND 2 <> :id]] + +00000 - - +-------- +[4] Query: [[SELECT 1 FROM DUAL WHERE 1 = :id AND '\'' = '''' AND 2 <> :id]] +1 +00000 - - +-------- +[5] Query: [[SELECT 'a', 'b\'' FROM DUAL WHERE '''' LIKE '\'' AND 1]] +a - b' +00000 - - +-------- +[6] Query: [[SELECT 'a''', '\'b\'' FROM DUAL WHERE '''' LIKE '\'' AND 1]] +a' - 'b' +00000 - - +-------- +[7] Query: [[SELECT UPPER(:id) FROM DUAL WHERE '1']] +1 +00000 - - +-------- +[8] Query: [[SELECT 1 FROM DUAL WHERE '\'']] + +00000 - - +-------- +[9] Query: [[SELECT 1 FROM DUAL WHERE :id AND '\0' OR :id]] +1 +00000 - - +-------- +[10] Query: [[SELECT 1 FROM DUAL WHERE 'a\f\n\0' AND 1 >= :id]] + +00000 - - +-------- +[11] Query: [[SELECT 1 FROM DUAL WHERE '\'' = '''']] +1 +00000 - - +-------- +[12] Query: [[SELECT '\n' '1 FROM DUAL WHERE '''' and :id']] + +1 FROM DUAL WHERE '' and :id +00000 - - +-------- +[13] Query: [[SELECT 1 'FROM DUAL WHERE :id AND '''' = '''' OR 1 = 1 AND ':id]] +1 +00000 - - +-------- \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug44327.php b/hphp/test/zend/bad/ext-pdo_mysql/bug44327.php new file mode 100644 index 000000000..f8403133b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug44327.php @@ -0,0 +1,32 @@ +prepare("SELECT 1 AS \"one\""); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_LAZY); + var_dump($row); + var_dump($row->{0}); + var_dump($row->one); + var_dump($row->queryString); + + print "----------------------------------\n"; + + @$db->exec("DROP TABLE test"); + $db->exec("CREATE TABLE test (id INT)"); + $db->exec("INSERT INTO test(id) VALUES (1)"); + $stmt = $db->prepare("SELECT id FROM test"); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_LAZY); + var_dump($row); + var_dump($row->queryString); + @$db->exec("DROP TABLE test"); + + print "----------------------------------\n"; + + $stmt = $db->prepare('foo'); + @$stmt->execute(); + $row = $stmt->fetch(); + var_dump($row->queryString); + +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug44327.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug44327.php.expectf new file mode 100644 index 000000000..733b77230 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug44327.php.expectf @@ -0,0 +1,20 @@ +object(PDORow)#%d (2) { + [%u|b%"queryString"]=> + %unicode|string%(17) "SELECT 1 AS "one"" + [%u|b%"one"]=> + %unicode|string%(1) "1" +} +%unicode|string%(1) "1" +%unicode|string%(1) "1" +%unicode|string%(17) "SELECT 1 AS "one"" +---------------------------------- +object(PDORow)#%d (2) { + [%u|b%"queryString"]=> + %unicode|string%(19) "SELECT id FROM test" + [%u|b%"id"]=> + %unicode|string%(1) "1" +} +%unicode|string%(19) "SELECT id FROM test" +---------------------------------- +HipHop Notice: %a +NULL \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug46292.php b/hphp/test/zend/bad/ext-pdo_mysql/bug46292.php new file mode 100644 index 000000000..c1c793218 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug46292.php @@ -0,0 +1,46 @@ +setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + $pdoDb->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + + $pdoDb->query('DROP TABLE IF EXISTS testz'); + + $pdoDb->query('CREATE TABLE testz (name VARCHAR(20) NOT NULL, value INT)'); + + $pdoDb->query("INSERT INTO testz VALUES ('myclass', 1), ('myclass2', 2), ('myclass', NULL), ('myclass3', NULL)"); + + $stmt = $pdoDb->prepare("SELECT * FROM testz"); + + var_dump($stmt->setFetchMode(PDO::FETCH_CLASS | PDO::FETCH_CLASSTYPE | PDO::FETCH_GROUP)); + $stmt->execute(); + + var_dump($stmt->fetch()); + var_dump($stmt->fetch()); + var_dump($stmt->fetchAll()); +?>exec('DROP TABLE IF EXISTS testz'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug46292.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug46292.php.expectf new file mode 100644 index 000000000..9b3101b05 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug46292.php.expectf @@ -0,0 +1,24 @@ +bool(true) +myclass::__construct() +object(myclass)#%d (1) { + [%u|b%"value"]=> + %unicode|string%(1) "1" +} +myclass::__construct() +object(myclass2)#%d (1) { + [%u|b%"value"]=> + %unicode|string%(1) "2" +} +myclass::__construct() +array(2) { + [0]=> + object(myclass)#%d (1) { + [%u|b%"value"]=> + NULL + } + [1]=> + object(stdClass)#%d (1) { + [%u|b%"value"]=> + NULL + } +} \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug53551.php b/hphp/test/zend/bad/ext-pdo_mysql/bug53551.php new file mode 100644 index 000000000..1aa22de07 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug53551.php @@ -0,0 +1,36 @@ +setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + +$createSql = "CREATE TABLE `bug53551` ( + `count` bigint(20) unsigned NOT NULL DEFAULT '0' +)"; + +$db->exec('drop table if exists bug53551'); +$db->exec($createSql); +$db->exec("insert into bug53551 set `count` = 1 "); +$db->exec("SET sql_mode = 'Traditional'"); +$sql = 'UPDATE bug53551 SET `count` = :count'; +$stmt = $db->prepare($sql); + +$values = array ( + 'count' => NULL, +); + +echo "1\n"; +$stmt->execute($values); +var_dump($stmt->errorInfo()); + +echo "2\n"; +$stmt->execute($values); +var_dump($stmt->errorInfo()); + +echo "\ndone\n"; + +?>exec('DROP TABLE IF EXISTS bug53551'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug53551.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug53551.php.expectf new file mode 100644 index 000000000..9bd6e5f9a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug53551.php.expectf @@ -0,0 +1,22 @@ +1 +HipHop Warning: %a +array(3) { + [0]=> + string(5) "23000" + [1]=> + int(1048) + [2]=> + string(29) "Column 'count' cannot be null" +} +2 +HipHop Warning: %a +array(3) { + [0]=> + string(5) "23000" + [1]=> + int(1048) + [2]=> + string(29) "Column 'count' cannot be null" +} + +done \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug53782.php b/hphp/test/zend/bad/ext-pdo_mysql/bug53782.php new file mode 100644 index 000000000..a0b8fac2e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug53782.php @@ -0,0 +1,24 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +$res = $conn->query('SELECT 0'); + +try { + $conn->query('ERROR'); +} catch (PDOException $e) { + echo "Caught: ".$e->getMessage()."\n"; +} + +foreach ($res as $k => $v) { + echo "Value: $v[0]\n"; +} + +echo "DONE"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug53782.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug53782.php.expectf new file mode 100644 index 000000000..f121566e5 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug53782.php.expectf @@ -0,0 +1,3 @@ +Caught: SQLSTATE[42000]: %s +Value: 0 +DONE \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug54929.php b/hphp/test/zend/bad/ext-pdo_mysql/bug54929.php new file mode 100644 index 000000000..89f7a9988 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug54929.php @@ -0,0 +1,29 @@ +prepare($query); + + if (!$stmt->execute(array("foo"))) { + var_dump($stmt->errorInfo()); + } else{ + var_dump($stmt->fetch(PDO::FETCH_ASSOC)); + } +} + +testQuery("/* ' */ select ? as f1 /* ' */"); +testQuery("/* '-- */ select ? as f1 /* *' */"); +testQuery("/* ' */ select ? as f1 --';"); +testQuery("/* ' */ select ? as f1 -- 'a;"); +testQuery("/*'**/ select ? as f1 /* ' */"); +testQuery("/*'***/ select ? as f1 /* ' */"); +testQuery("/*'**a ***b / **** +****** +**/ select ? as f1 /* ' */"); + +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug54929.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug54929.php.expectf new file mode 100644 index 000000000..fdbb67424 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug54929.php.expectf @@ -0,0 +1,33 @@ +array(1) { + ["f1"]=> + string(3) "foo" +} +array(1) { + ["f1"]=> + string(3) "foo" +} +HipHop Warning: %a +array(3) { + [0]=> + string(5) "42000" + [1]=> + int(1064) + [2]=> + string(149) "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '--'' at line 1" +} +array(1) { + ["f1"]=> + string(3) "foo" +} +array(1) { + ["f1"]=> + string(3) "foo" +} +array(1) { + ["f1"]=> + string(3) "foo" +} +array(1) { + ["f1"]=> + string(3) "foo" +} \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_33689.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_33689.php new file mode 100644 index 000000000..ceeb74c77 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_33689.php @@ -0,0 +1,29 @@ +exec('CREATE TABLE test (bar INT NOT NULL)'); +$db->exec('INSERT INTO test VALUES(1)'); + +var_dump($db->query('SELECT * from test')); +foreach ($db->query('SELECT * from test') as $row) { + print_r($row); +} + +$stmt = $db->prepare('SELECT * from test'); +print_r($stmt->getColumnMeta(0)); +$stmt->execute(); +$tmp = $stmt->getColumnMeta(0); + +// libmysql and mysqlnd will show the pdo_type entry at a different position in the hash +if (!isset($tmp['pdo_type']) || (isset($tmp['pdo_type']) && $tmp['pdo_type'] != 2)) + printf("Expecting pdo_type = 2 got %s\n", $tmp['pdo_type']); +else + unset($tmp['pdo_type']); + +print_r($tmp); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_33689.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_33689.php.expectf new file mode 100644 index 000000000..82f58583a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_33689.php.expectf @@ -0,0 +1,22 @@ +object(PDOStatement)#%d (1) { + [%u|b%"queryString"]=> + %unicode|string%(18) "SELECT * from test" +} +Array +( + [bar] => 1 + [0] => 1 +) +Array +( + [native_type] => LONG + [flags] => Array + ( + [0] => not_null + ) + + [table] => test + [name] => bar + [len] => 11 + [precision] => 0 +) \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_39483.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_39483.php new file mode 100644 index 000000000..57e0ce82f --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_39483.php @@ -0,0 +1,8 @@ +setAttribute(PDO::ATTR_EMULATE_PREPARES, TRUE); +$stmt = $db->prepare('SELECT UPPER(\'\0:D\0\'),?'); +$stmt->execute(array(1)); +var_dump($stmt->fetchAll(PDO::FETCH_NUM)); diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_39483.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_39483.php.expectf new file mode 100644 index 000000000..bac1b2279 Binary files /dev/null and b/hphp/test/zend/bad/ext-pdo_mysql/bug_39483.php.expectf differ diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_39858.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_39858.php new file mode 100644 index 000000000..59757d6f7 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_39858.php @@ -0,0 +1,47 @@ +setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + +function bug_39858($db) { + + $db->exec("DROP PROCEDURE IF EXISTS p"); + $db->exec(" + CREATE PROCEDURE p() + NOT DETERMINISTIC + CONTAINS SQL + SQL SECURITY DEFINER + COMMENT '' + BEGIN + SELECT 2 * 2; + END;"); + + $stmt = $db->prepare("CALL p()"); + $stmt->execute(); + do { + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + } while ($stmt->nextRowset()); + + $stmt = $db->prepare("CALL p()"); + $stmt->execute(); + do { + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + } while ($stmt->nextRowset()); + $stmt->closeCursor(); + +} + +printf("Emulated Prepared Statements...\n"); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +bug_39858($db); + +printf("Native Prepared Statements...\n"); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +bug_39858($db); + +print "done!"; +?>exec("DROP PROCEDURE IF EXISTS p"); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_39858.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_39858.php.expectf new file mode 100644 index 000000000..e562191ca --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_39858.php.expectf @@ -0,0 +1,31 @@ +Emulated Prepared Statements... +array(1) { + [0]=> + array(1) { + [%u|b%"2 * 2"]=> + %unicode|string%(1) "4" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"2 * 2"]=> + %unicode|string%(1) "4" + } +} +Native Prepared Statements... +array(1) { + [0]=> + array(1) { + [%u|b%"2 * 2"]=> + %unicode|string%(1) "4" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"2 * 2"]=> + %unicode|string%(1) "4" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_41125.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_41125.php new file mode 100644 index 000000000..aa10523cd --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_41125.php @@ -0,0 +1,23 @@ +exec("DROP TABLE IF EXISTS test"); + +// And now allow the evil to do his work +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +$sql = "CREATE TABLE IF NOT EXISTS test(id INT); INSERT INTO test(id) VALUES (1); SELECT * FROM test; INSERT INTO test(id) VALUES (2); SELECT * FROM test;"; +// NOTE: This will fail, it is OK to fail - you must not mix DML/DDL and SELECT +// The PDO API does not support multiple queries properly! +// Read http://blog.ulf-wendel.de/?p=192 +// Compare MySQL C-API documentation +$stmt = $db->query($sql); +do { + var_dump($stmt->fetchAll()); +} while ($stmt->nextRowset()); + +print "done!"; +?>exec("DROP TABLE IF EXISTS test"); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_41125.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_41125.php.expectf new file mode 100644 index 000000000..4ec83465c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_41125.php.expectf @@ -0,0 +1,4 @@ +HipHop Warning: %a +array(0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_41698.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_41698.php new file mode 100644 index 000000000..789784243 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_41698.php @@ -0,0 +1,14 @@ +exec('CREATE TABLE test(floatval DECIMAL(8,6))'); +$db->exec('INSERT INTO test VALUES(2.34)'); +$value=4.56; +$stmt = $db->prepare('INSERT INTO test VALUES(?)'); +$stmt->execute(array($value)); +var_dump($db->query('SELECT * from test')->fetchAll(PDO::FETCH_ASSOC)); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_41698.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_41698.php.expectf new file mode 100644 index 000000000..af01559cf --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_41698.php.expectf @@ -0,0 +1,12 @@ +array(2) { + [0]=> + array(1) { + [%u|b%"floatval"]=> + %unicode|string%(8) "2.340000" + } + [1]=> + array(1) { + [%u|b%"floatval"]=> + %unicode|string%(8) "4.560000" + } +} \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_41997.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_41997.php new file mode 100644 index 000000000..884e1bdb3 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_41997.php @@ -0,0 +1,18 @@ +exec('DROP PROCEDURE IF EXISTS p'); +$db->exec('CREATE PROCEDURE p() BEGIN SELECT 1 AS "one"; END'); + +$stmt = $db->query("CALL p()"); +do { + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); +} while ($stmt->nextRowset()); +var_dump($stmt->errorInfo()); + +$stmt = $db->query('SELECT 2 AS "two"'); +var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); +var_dump($stmt->errorInfo()); +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_41997.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_41997.php.expectf new file mode 100644 index 000000000..f7f829753 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_41997.php.expectf @@ -0,0 +1,31 @@ +array(1) { + [0]=> + array(1) { + [%u|b%"one"]=> + %unicode|string%(1) "1" + } +} +array(3) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + NULL + [2]=> + NULL +} +array(1) { + [0]=> + array(1) { + [%u|b%"two"]=> + %unicode|string%(1) "2" + } +} +array(3) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + NULL + [2]=> + NULL +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_42499.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_42499.php new file mode 100644 index 000000000..f7174a714 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_42499.php @@ -0,0 +1,36 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec("CREATE TABLE test(id CHAR(1)); INSERT INTO test(id) VALUES ('a')"); + + $stmt = $db->query('SELECT id AS _id FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // You must not use exec() to run statements that create a result set! + $db->exec('SELECT id FROM test'); + // This will bail at you because you have not fetched the SELECT results: this is not a bug! + $db->exec("INSERT INTO test(id) VALUES ('b')"); + +} + +print "Emulated Prepared Statements...\n"; +$db = MySQLPDOTest::factory(); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); +bug_42499($db); + +print "Native Prepared Statements...\n"; +$db = MySQLPDOTest::factory(); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); +bug_42499($db); + +$db = MySQLPDOTest::factory(); +$db->exec('DROP TABLE IF EXISTS test'); + +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_42499.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_42499.php.expectf new file mode 100644 index 000000000..652db783c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_42499.php.expectf @@ -0,0 +1,19 @@ +Emulated Prepared Statements... +array(1) { + [0]=> + array(1) { + [%u|b%"_id"]=> + %unicode|string%(1) "a" + } +} +HipHop Warning: %a +Native Prepared Statements... +array(1) { + [0]=> + array(1) { + [%u|b%"_id"]=> + %unicode|string%(1) "a" + } +} +HipHop Warning: %a +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_43371.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_43371.php new file mode 100644 index 000000000..1b7ca1660 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_43371.php @@ -0,0 +1,8 @@ + true)); + +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_43371.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_43371.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_43371.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_44454.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_44454.php new file mode 100644 index 000000000..d8d887c96 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_44454.php @@ -0,0 +1,63 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec('CREATE TABLE test(a INT, b INT, UNIQUE KEY idx_ab (a, b))'); + $db->exec('INSERT INTO test(a, b) VALUES (1, 1)'); + + $stmt = $db->query('SELECT a, b FROM test'); + printf("... SELECT has returned %d row...\n", $stmt->rowCount()); + while ($row = $stmt->fetch()) { + try { + printf("... INSERT should fail...\n"); + $db->exec('INSERT INTO test(a, b) VALUES (1, 1)'); + } catch (Exception $e) { + printf("... STMT - %s\n", var_export($stmt->errorCode(), true)); + printf("... PDO - %s\n", var_export($db->errorInfo(), true)); + } + } + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec('CREATE TABLE test(a INT, b INT, UNIQUE KEY idx_ab (a, b))'); + $db->exec('INSERT INTO test(a, b) VALUES (1, 1)'); + + } catch (Exception $e) { + printf("... While error %s\n", $e->getMessage()); ; + } + + $stmt = $db->query('SELECT a, b FROM test'); + printf("... SELECT has returned %d row...\n", $stmt->rowCount()); + foreach ($stmt as $row) { + try { + printf("... INSERT should fail...\n"); + $db->exec('INSERT INTO test(a, b) VALUES (1, 1)'); + } catch (Exception $e) { + printf("... STMT - %s\n", var_export($stmt->errorCode(), true)); + printf("... PDO - %s\n", var_export($db->errorInfo(), true)); + } + } + +} + +$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +print "Native Prepared Statements\n"; +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +bug_44454($db); + +print "\nEmulated Prepared Statements\n"; +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +bug_44454($db); + +print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_44454.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_44454.php.expectf new file mode 100644 index 000000000..d45b6ab0a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_44454.php.expectf @@ -0,0 +1,36 @@ +Native Prepared Statements +... SELECT has returned 1 row... +... INSERT should fail... +... STMT - '00000' +... PDO - array ( + 0 => '23000', + 1 => 1062, + 2 => 'Duplicate entry \'1-1\' for key %s', +) +... SELECT has returned 1 row... +... INSERT should fail... +... STMT - '00000' +... PDO - array ( + 0 => '23000', + 1 => 1062, + 2 => 'Duplicate entry \'1-1\' for key %s', +) + +Emulated Prepared Statements +... SELECT has returned 1 row... +... INSERT should fail... +... STMT - '00000' +... PDO - array ( + 0 => '23000', + 1 => 1062, + 2 => 'Duplicate entry \'1-1\' for key %s', +) +... SELECT has returned 1 row... +... INSERT should fail... +... STMT - '00000' +... PDO - array ( + 0 => '23000', + 1 => 1062, + 2 => 'Duplicate entry \'1-1\' for key %s', +) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_44707.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_44707.php new file mode 100644 index 000000000..9ceadec5c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_44707.php @@ -0,0 +1,52 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec('CREATE TABLE test(id INT, mybool TINYINT)'); + + $id = 1; + $mybool = false; + var_dump($mybool); + + $stmt = $db->prepare('INSERT INTO test(id, mybool) VALUES (?, ?)'); + $stmt->bindParam(1, $id); + // From MySQL 4.1 on boolean and TINYINT don't match! INSERT will fail. + // Versions prior to 4.1 have a weak test and will accept this. + $stmt->bindParam(2, $mybool, PDO::PARAM_BOOL); + var_dump($mybool); + + $stmt->execute(); + var_dump($mybool); + + $stmt = $db->query('SELECT * FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $db->prepare('INSERT INTO test(id, mybool) VALUES (?, ?)'); + $stmt->bindParam(1, $id); + // INT and integer work well together + $stmt->bindParam(2, $mybool, PDO::PARAM_INT); + $stmt->execute(); + + $stmt = $db->query('SELECT * FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + +} + + +/* +// This is beyond the control of the driver... - the driver never gets in touch with bound values +print "Emulated Prepared Statements\n"; +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +bug_44707($db); +*/ + +print "Native Prepared Statements\n"; +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +bug_44707($db); + +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_44707.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_44707.php.expectf new file mode 100644 index 000000000..3361279a2 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_44707.php.expectf @@ -0,0 +1,16 @@ +Native Prepared Statements +bool(false) +bool(false) +bool(false) +array(0) { +} +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"mybool"]=> + %unicode|string%(1) "0" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_45120.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_45120.php new file mode 100644 index 000000000..a46925295 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_45120.php @@ -0,0 +1,34 @@ +prepare("SELECT 1 AS 'one'"); + if (true !== $stmt->execute()) + printf("[001] Execute has failed: %s\n", var_export($stmt->errorInfo(), true)); + + $res = $stmt->fetch(PDO::FETCH_ASSOC); + if ($res['one'] != 1) + printf("[002] Wrong results: %s\n", var_export($res, true)); + + if (true !== $stmt->execute()) + printf("[003] Execute has failed: %s\n", var_export($stmt->errorInfo(), true)); + + $res = $stmt->fetch(PDO::FETCH_ASSOC); + if ($res['one'] != 1) + printf("[004] Wrong results: %s\n", var_export($res, true)); + +} + +print "Emulated Prepared Statements\n"; +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +bug_45120($db); + +print "Native Prepared Statements\n"; +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +bug_45120($db); + +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_45120.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_45120.php.expectf new file mode 100644 index 000000000..d922f6682 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_45120.php.expectf @@ -0,0 +1,3 @@ +Emulated Prepared Statements +Native Prepared Statements +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_50323.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_50323.php new file mode 100644 index 000000000..44d4e6a62 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_50323.php @@ -0,0 +1,46 @@ + $v) { + $tmp = explode('=', $v); + if (count($tmp) == 2) + $old_options[$tmp[0]] = $tmp[1]; + } + + $options = $old_options; + foreach ($new_options as $k => $v) + $options[$k] = $v; + + $dsn = 'mysql:'; + foreach ($options as $k => $v) + $dsn .= sprintf('%s=%s;', $k, $v); + + $dsn = substr($dsn, 0, strlen($dsn) -1); + + return $dsn; + } + + +if (1 === @$db->exec('CREATE DATABASE `crazy;dbname`')) { + $dsn = changeDSN(getenv('PDOTEST_DSN'), array('dbname' => 'crazy;;dbname')); + $user = getenv('PDOTEST_USER'); + $pass = getenv('PDOTEST_PASS'); + + new PDO($dsn, $user, $pass); +} +echo 'done!'; +?>exec('DROP DATABASE IF EXISTS `crazy;dbname`'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_50323.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_50323.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_50323.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_51670.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_51670.php new file mode 100644 index 000000000..86d2b3a77 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_51670.php @@ -0,0 +1,11 @@ +prepare('SELECT 1 AS num'); +$query->execute(); +if(!is_array($query->getColumnMeta(0))) die('FAIL!'); +$query->nextRowset(); +$query->execute(); +if(!is_array($query->getColumnMeta(0))) die('FAIL!'); +echo 'done!'; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_51670.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_51670.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_51670.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_61207.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_61207.php new file mode 100644 index 000000000..3a9bbe559 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_61207.php @@ -0,0 +1,77 @@ +query('DROP TABLE IF EXISTS test'); +$db->query('create table `test`( `id` int )'); + +$handle1 = $db->prepare('insert into test(id) values(1); + select * from test where id = ?; + update test set id = 2 where id = ?;'); + +$handle1->bindValue('1', '1'); +$handle1->bindValue('2', '1'); + +$handle1->execute(); +$i = 1; +print("Handle 1:\n"); +do { + print('Rowset ' . $i++ . "\n"); + if ($handle1->columnCount() > 0) + print("Results detected\n"); +} while($handle1->nextRowset()); + +$handle2 = $db->prepare('select * from test where id = ?; + update test set id = 1 where id = ?;'); + +$handle2->bindValue('1', '2'); +$handle2->bindValue('2', '2'); + +$handle2->execute(); + +$i = 1; +print("Handle 2:\n"); +do { + print('Rowset ' . $i++ . "\n"); + if ($handle2->columnCount() > 0) + print("Results detected\n"); +} while($handle2->nextRowset()); + +$handle3 = $db->prepare('update test set id = 2 where id = ?; + select * from test where id = ?;'); + +$handle3->bindValue('1', '1'); +$handle3->bindValue('2', '2'); + +$handle3->execute(); + +$i = 1; +print("Handle 3:\n"); +do { + print('Rowset ' . $i++ . "\n"); + if ($handle3->columnCount() > 0) + print("Results detected\n"); +} while($handle3->nextRowset()); + +$handle4 = $db->prepare('insert into test(id) values(3); + update test set id = 2 where id = ?; + select * from test where id = ?;'); + +$handle4->bindValue('1', '3'); +$handle4->bindValue('2', '2'); + +$handle4->execute(); + +$i = 1; +print("Handle 4:\n"); +do { + print('Rowset ' . $i++ . "\n"); + if ($handle1->columnCount() > 0) + print("Results detected\n"); +} while($handle1->nextRowset()); + +$db->query("DROP TABLE test"); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_61207.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_61207.php.expectf new file mode 100644 index 000000000..07e1d2f0c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_61207.php.expectf @@ -0,0 +1,18 @@ +Handle 1: +Rowset 1 +Rowset 2 +Results detected +Rowset 3 +Handle 2: +Rowset 1 +Results detected +Rowset 2 +Handle 3: +Rowset 1 +Rowset 2 +Results detected +Handle 4: +Rowset 1 +Rowset 2 +Rowset 3 +Results detected \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_61411.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_61411.php new file mode 100644 index 000000000..772ee4d5d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_61411.php @@ -0,0 +1,24 @@ +prepare("SELECT 1"); +$stmt->execute(); + +foreach ($stmt as $line) { + var_dump($line); +} + +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_61411.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_61411.php.expectf new file mode 100644 index 000000000..450a3a19e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_61411.php.expectf @@ -0,0 +1,7 @@ +array(2) { + [1]=> + int(1) + [2]=> + int(1) +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_61755.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_61755.php new file mode 100644 index 000000000..c9d061342 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_61755.php @@ -0,0 +1,23 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + +echo "NULL-Byte before first placeholder:\n"; +$s = $db->prepare("SELECT \"a\0b\", ?"); +$s->bindValue(1,"c"); +$s->execute(); +$r = $s->fetch(); +echo "Length of item 0: ".strlen($r[0]).", Value of item 1: ".$r[1]."\n"; + +echo "\nOpen comment:\n"; +try { + $s = $db->prepare("SELECT /*"); + $s->execute(); +} catch (Exception $e) { + echo "Error code: ".$e->getCode()."\n"; +} + +echo "\ndone!\n"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_61755.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_61755.php.expectf new file mode 100644 index 000000000..720ea3c8b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_61755.php.expectf @@ -0,0 +1,7 @@ +NULL-Byte before first placeholder: +Length of item 0: 3, Value of item 1: c + +Open comment: +Error code: 42000 + +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_12925.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_12925.php new file mode 100644 index 000000000..940fd76dd --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_12925.php @@ -0,0 +1,33 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec('CREATE TABLE test(id CHAR(1))'); + $db->exec("INSERT INTO test(id) VALUES ('a')"); + $stmt = $db->prepare("UPDATE test SET id = 'b'"); + $stmt->execute(); + $stmt = $db->prepare("UPDATE test SET id = 'c'"); + $stmt->execute(); + $stmt = $db->prepare('SELECT id FROM test'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt->closeCursor(); + +} + +printf("Emulated...\n"); +$db = MySQLPDOTest::factory(); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +bug_pecl_1295($db); + +printf("Native...\n"); +$db = MySQLPDOTest::factory(); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +bug_pecl_1295($db); + +$db->exec('DROP TABLE IF EXISTS test'); +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_12925.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_12925.php.expectf new file mode 100644 index 000000000..da55fea34 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_12925.php.expectf @@ -0,0 +1,17 @@ +Emulated... +array(1) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "c" + } +} +Native... +array(1) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "c" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_7976.php b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_7976.php new file mode 100644 index 000000000..0a09ef90f --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_7976.php @@ -0,0 +1,35 @@ +exec('DROP PROCEDURE IF EXISTS p'); + $db->exec('CREATE PROCEDURE p() BEGIN SELECT "1" AS _one; END;'); + + $stmt = $db->query('CALL p()'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt->closeCursor(); + + $stmt = $db->query('CALL p()'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt->closeCursor(); + +} + +printf("Emulated...\n"); +$db = MySQLPDOTest::factory(); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); +bug_pecl_7976($db); + +printf("Native...\n"); +$db = MySQLPDOTest::factory(); +$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); +bug_pecl_7976($db); + +print "done!"; +?>exec('DROP PROCEDURE IF EXISTS p'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_7976.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_7976.php.expectf new file mode 100644 index 000000000..cbb3dc799 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/bug_pecl_7976.php.expectf @@ -0,0 +1,31 @@ +Emulated... +array(1) { + [0]=> + array(1) { + [%u|b%"_one"]=> + %unicode|string%(1) "1" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"_one"]=> + %unicode|string%(1) "1" + } +} +Native... +array(1) { + [0]=> + array(1) { + [%u|b%"_one"]=> + %unicode|string%(1) "1" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"_one"]=> + %unicode|string%(1) "1" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/last_insert_id.php b/hphp/test/zend/bad/ext-pdo_mysql/last_insert_id.php new file mode 100644 index 000000000..3a5e5e825 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/last_insert_id.php @@ -0,0 +1,11 @@ +query("CREATE TABLE test (id int auto_increment primary key, num int)")); + +print_r($db->query("INSERT INTO test (id, num) VALUES (23, 42)")); + +print_r($db->query("INSERT INTO test (num) VALUES (451)")); + +print_r($db->lastInsertId()); \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/last_insert_id.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/last_insert_id.php.expectf new file mode 100644 index 000000000..c8518ec37 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/last_insert_id.php.expectf @@ -0,0 +1,13 @@ +PDOStatement Object +( + [queryString] => CREATE TABLE test (id int auto_increment primary key, num int) +) +PDOStatement Object +( + [queryString] => INSERT INTO test (id, num) VALUES (23, 42) +) +PDOStatement Object +( + [queryString] => INSERT INTO test (num) VALUES (451) +) +24 \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct.php new file mode 100644 index 000000000..1cd43892c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct.php @@ -0,0 +1,280 @@ +getMessage(), + (isset($db) && is_object($db)) ? $db->errorCode() : 'n/a', + (isset($db) && is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + + return ''; + } + + try { + + if (NULL !== ($db = @new PDO())) + printf("[001] Too few parameters\n"); + + print tryandcatch(2, '$db = new PDO(chr(0));'); + print tryandcatch(3, '$db = new PDO("a" . chr(0) . "b");'); + print tryandcatch(4, '$db = new PDO("MYSQL");'); + print tryandcatch(5, '$db = new PDO("mysql");'); + print tryandcatch(6, '$db = new PDO("mysql ");'); + print tryandcatch(7, '$db = new PDO("fantasyandfriends :");'); + + $dsn = PDO_MYSQL_TEST_DSN; + // MySQL Server might accept anonymous connections, don't + // print anything + tryandcatch(8, '$db = new PDO("' . $dsn . '");'); + + $user = 'dontcreatesuchauser'; + $pass = 'withthispassword'; + print tryandcatch(9, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");'); + + // should fail + $dsn = 'mysql:'; + print tryandcatch(10, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");'); + + $dsn = PDO_MYSQL_TEST_DSN; + $user = PDO_MYSQL_TEST_USER; + $pass = PDO_MYSQL_TEST_PASS; + // should work... + $db = new PDO($dsn, $user, $pass); + + $dsn = 'mysql:invalid=foo'; + print tryandcatch(11, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");'); + + $dsn = 'mysql:' . str_repeat('howmuch=canpdoeat;', 1000); + print tryandcatch(12, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");'); + + $dsn = 'mysql:' . str_repeat('abcdefghij', 1024 * 10) . '=somevalue'; + print tryandcatch(13, '$db = new PDO("' . $dsn . '", "' . $user . '", "' . $pass . '");'); + + if (PDO_MYSQL_TEST_HOST) { + $host = PDO_MYSQL_TEST_HOST; + $invalid_host = $host . 'invalid'; + + // last host specification should be the one used + $dsn = MySQLPDOTest::getDSN(array('host' => $host), 'host=' . $invalid_host); + try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) { + $tmp = $e->getMessage(); + if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005') && !stristr($tmp, '2002')) + printf("[014] Cannot find proper error codes: %s\n", $tmp); + } + + $dsn = MySQLPDOTest::getDSN(array('host' => $invalid_host), 'host=' . $host); + try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) { + printf("[015] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + + $invalid_host = '-' . chr(0); + + $dsn = MySQLPDOTest::getDSN(array('host' => $invalid_host)); + try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) { + $tmp = $e->getMessage(); + if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005') && !stristr($tmp, '2002')) + printf("[016] Cannot find proper error codes: %s\n", $tmp); + } + + // parsing should not get confused by chr(0) + $dsn = MySQLPDOTest::getDSN(array('host' => $invalid_host), 'host=' . $host); + try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) { + printf("[017] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + + } + + // what about long values for a valid option ... + // hostnames > 1024 chars break on some NIS-enabled FreeBSD... + $dsn = MySQLPDOTest::getDSN(array('host' => str_repeat('0123456789', 100))); + try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) { + $tmp = $e->getMessage(); + if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005') && !stristr($tmp, '2002')) + printf("[018] Cannot find proper error codes: %s\n", $tmp); + } + + if (PDO_MYSQL_TEST_PORT && (PDO_MYSQL_TEST_SOCKET == '')) { + // Playing with the port makes only sense if no socket gets used + + $port = PDO_MYSQL_TEST_PORT; + // let's hope we don't hit a MySQL running on that port... + $invalid_port = $port * 2; + + $dsn = MySQLPDOTest::getDSN(array('port' => $port), 'port=' . $invalid_port); + try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) { + $tmp = $e->getMessage(); + if (!stristr($tmp, 'HY000') && !stristr($tmp, '2005')) + printf("[019] Cannot find proper error codes: %s\n", $tmp); + } + + $dsn = MySQLPDOTest::getDSN(array('port' => $invalid_port), 'port=' . $port); + try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) { + printf("[020] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + + $invalid_port = 'abc'; + $dsn = MySQLPDOTest::getDSN(array('port' => $port), 'port=' . $invalid_port); + try { + $db = @new PDO($dsn, $user, $pass); + // atoi('abc') = 0, 0 -> fallback to default 3306 -> may or may not fail! + } catch (PDOException $e) { + } + + } + + if (PDO_MYSQL_TEST_DB) { + $db = PDO_MYSQL_TEST_DB; + $invalid_db = 'letshopeitdoesnotexist'; + + $dsn = MySQLPDOTest::getDSN(array('dbname' => $db), 'dbname=' . $invalid_db); + try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) { + $tmp = $e->getMessage(); + if (!stristr($tmp, '42000') && !stristr($tmp, '1049')) + printf("[022] Cannot find proper error codes: %s\n", $tmp); + } + + $dsn = MySQLPDOTest::getDSN(array('dbname' => $invalid_db), 'dbname=' . $db); + try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) { + printf("[023] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + + } + + if (PDO_MYSQL_TEST_SOCKET && (stristr(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_SOCKET) !== false)) { + $socket = PDO_MYSQL_TEST_SOCKET; + $invalid_socket = '/lets/hope/it/does/not/exist'; + + $dsn = MySQLPDOTest::getDSN(array('unix_socket' => $socket), 'unix_socket=' . $invalid_socket); + try { $db = @new PDO($dsn, $user, $pass); assert(false); printf("%s\n", $dsn); } catch (PDOException $e) { + $tmp = $e->getMessage(); + if (!stristr($tmp, 'HY000') && !stristr($tmp, '2002')) + printf("[024] Cannot find proper error codes: %s\n", $tmp); + } + + $dsn = MySQLPDOTest::getDSN(array('unix_socket' => $invalid_socket), 'unix_socket=' . $socket); + try { $db = @new PDO($dsn, $user, $pass); } catch (PDOException $e) { + printf("[025] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + + } + + $have_charset_support = false; + $dsn = MySQLPDOTest::getDSN(); + try { + $db = new PDO($dsn, $user, $pass); + $stmt = $db->query('SELECT VERSION() as _version'); + $version = $stmt->fetch(PDO::FETCH_ASSOC); + + $tmp = explode('.', $version['_version']); + if ((count($tmp) == 3) && + (($tmp[0] >= 4 && $tmp[1] >= 1) || ($tmp[0] >= 5))) { + // MySQL Server 4.1 - charset support available + $have_charset_support = true; + } + + } catch (PDOException $e) { + printf("[026] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + + if (PDO_MYSQL_TEST_CHARSET) { + $charset = PDO_MYSQL_TEST_CHARSET; + $invalid_charset = 'invalid'; + + if ($have_charset_support) { + $dsn = MySQLPDOTest::getDSN(); + $db = new PDO($dsn, $user, $pass); + $stmt = $db->query(sprintf('SHOW CHARACTER SET LIKE "%s"', $charset)); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $have_charset = (empty($tmp)) ? false : true; + + if ($have_charset) { + $dsn = MySQLPDOTest::getDSN(array('charset' => $charset), 'charset=' . $invalid_charset); + try { + $db = @new PDO($dsn, $user, $pass); + /* NOTE: MySQL does a fallback to the charset suggested during the handshake - no error - no bug! */ + } catch (PDOException $e) { + $tmp = $e->getMessage(); + /* TODO: add proper codes */ + if (!stristr($tmp, 'sqlstatecode') || !stristr($tmp, 'mysqlinternalerrcode')) + printf("[027] TODO - Cannot find proper error codes: %s\n", $tmp); + } + + $dsn = MySQLPDOTest::getDSN(array('charset' => $invalid_charset), 'charset=' . $charset); + try { + $db = @new PDO($dsn, $user, $pass); + /* Strictly speaking we should test more: character_set_client, character_set_results, and character_set_connection */ + $stmt = $db->query('SELECT @@character_set_connection AS _charset'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + if ($tmp['_charset'] != $charset) + printf("[028] Character sets has not been set, @@character_set_connection reports '%s', expecting '%s'", + $tmp['_charset'], $charset); + } catch (PDOException $e) { + printf("[029] DSN=%s, %s\n", $dsn, $e->getMessage()); + } + } else { + printf("[030] You're trying to run the tests with charset '%s' which seems not supported by the server!", $charset); + } + + } + + } + + if ($have_charset_support) { + // In case the PDO_MYSQL_TEST_CHARSET interferes with any defaults + // we do another test to verify that the charset has been set. + $dsn = MySQLPDOTest::getDSN(); + $db = new PDO($dsn, $user, $pass); + $stmt = $db->query('SHOW CHARACTER SET LIKE "latin1"'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $have_latin1 =(empty($tmp)) ? false : true; + $stmt = $db->query('SHOW CHARACTER SET LIKE "latin2"'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $have_latin2 =(empty($tmp)) ? false : true; + + if ($have_latin1 && $have_latin2) { + // very likely we do have both of them... + try { + $dsn = MySQLPDOTest::getDSN(array('charset' => 'latin1')); + $db = new PDO($dsn, $user, $pass); + $stmt = $db->query('SELECT @@character_set_connection AS _charset'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + if ($tmp['_charset'] != 'latin1') + printf("[031] DSN = %s, Character sets has not been set, @@character_set_connection reports '%s', expecting '%s'", + $dsn, $tmp['_charset'], 'latin1'); + + } catch (PDOException $e) { + printf("[032] %s\n", $e->getMessage()); + } + + try { + $dsn = MySQLPDOTest::getDSN(array('charset' => 'latin2')); + $db = new PDO($dsn, $user, $pass); + $stmt = $db->query('SELECT @@character_set_connection AS _charset'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + if ($tmp['_charset'] != 'latin2') + printf("[033] DSN = %s, character sets has not been set, @@character_set_connection reports '%s', expecting '%s'", + $dsn, $tmp['_charset'], 'latin2'); + + } catch (PDOException $e) { + printf("[034] %s\n", $e->getMessage()); + } + + } + } + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + (is_object($db)) ? $db->errorCode() : 'n/a', + (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct.php.expectf new file mode 100644 index 000000000..58c938a23 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct.php.expectf @@ -0,0 +1,10 @@ +[002] invalid data source name, [n/a] n/a +[003] invalid data source name, [n/a] n/a +[004] invalid data source name, [n/a] n/a +[005] invalid data source name, [n/a] n/a +[006] invalid data source name, [n/a] n/a +[007] could not find driver, [n/a] n/a +[009] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a +[010] SQLSTATE[%s] [1045] Access denied for user 'dont%s'@'%s' (using password: YES), [n/a] n/a +[017] DSN=%s, SQLSTATE[%s] [%d] %s +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options.php new file mode 100644 index 000000000..310b79ef7 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options.php @@ -0,0 +1,154 @@ + $value)); + if (!is_object($db) || ($value !== ($tmp = @$db->getAttribute($option)))) + printf("[%03d] Execting '%s'/%s got '%s'/%s' for options '%s'\n", + $offset, + $value, gettype($value), + $tmp, gettype($tmp), + $option_desc); + } catch (PDOException $e) { + printf("[%03d] %s\n", $offset, $e->getMessage()); + } + + } + + try { + + $dsn = MySQLPDOTest::getDSN(); + $user = PDO_MYSQL_TEST_USER; + $pass = PDO_MYSQL_TEST_PASS; + + $valid_options = array( + /* pdo_dbh.c */ + PDO::ATTR_PERSISTENT => 'PDO::ATTR_PERSISTENT', + PDO::ATTR_AUTOCOMMIT => 'PDO::ATTR_AUTOCOMMIT', + /* mysql_driver.c */ + /* TODO Possible bug PDO::ATTR_TIMEOUT != MYSQLI_OPT_CONNECT_TIMEOUT*/ + PDO::ATTR_TIMEOUT => 'PDO::ATTR_TIMEOUT', + PDO::ATTR_EMULATE_PREPARES => 'PDO::ATTR_EMULATE_PREPARES', + + PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => 'PDO::MYSQL_ATTR_USE_BUFFERED_QUERY', + PDO::MYSQL_ATTR_LOCAL_INFILE => 'PDO::MYSQL_ATTR_LOCAL_INFILE', + PDO::MYSQL_ATTR_DIRECT_QUERY => 'PDO::MYSQL_ATTR_DIRECT_QUERY', + + PDO::MYSQL_ATTR_INIT_COMMAND => 'PDO::MYSQL_ATTR_INIT_COMMAND', + ); + + $defaults = array( + PDO::ATTR_PERSISTENT => false, + PDO::ATTR_AUTOCOMMIT => 1, + /* TODO - why is this a valid option if getAttribute() does not support it?! */ + PDO::ATTR_TIMEOUT => false, + PDO::ATTR_EMULATE_PREPARES => 1, + PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => 1, + /* TODO getAttribute() does not handle it */ + PDO::MYSQL_ATTR_LOCAL_INFILE => false, + /* TODO getAttribute() does not handle it */ + PDO::MYSQL_ATTR_DIRECT_QUERY => 1, + PDO::MYSQL_ATTR_INIT_COMMAND => '', + ); + + if (NULL !== ($db = @new PDO($dsn, $user, $pass, 'wrong type'))) + printf("[001] Expecting NULL got %s/%s\n", gettype($db), $db); + + if (!is_object($db = new PDO($dsn, $user, $pass, array()))) + printf("[002] Expecting object got %s/%s¸\n", gettype($db), $db); + + do { + $invalid = mt_rand(-1000, 1000); + } while (isset($valid_options[$invalid])); + if (is_object($db = new PDO($dsn, $user, $pass, array($invalid => true)))) + printf("[003] [TODO][CHANGEREQUEST] Please, lets not ignore invalid options and bail out!\n"); + + $db = new PDO($dsn, $user, $pass); + foreach ($valid_options as $option => $name) { + /* TODO getAttribute() is pretty poor in supporting the options, suppress errors */ + $tmp = @$db->getAttribute($option); + if ($tmp !== $defaults[$option]) + printf("[003a] Expecting default value for '%s' of '%s'/%s, getAttribute() reports setting '%s'/%s\n", + $name, $defaults[$option], gettype($defaults[$option]), + $tmp, gettype($tmp)); + } + + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_AUTOCOMMIT => true)); + if (!is_object($db) || !$db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[004] Autocommit should be on\n"); + + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_AUTOCOMMIT => false)); + if (!is_object($db) || $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[005] Autocommit should be off\n"); + + /* TODO: no way to check ATTR_TIMEOUT settings */ + if (!is_object($db = new PDO($dsn, $user, $pass, array(PDO::ATTR_TIMEOUT => 10)))) + printf("[006] ATTR_TIMEOUT should be accepted\n"); + + if (!is_object($db = new PDO($dsn, $user, $pass, array(PDO::ATTR_TIMEOUT => PHP_INT_MAX)))) + printf("[007] ATTR_TIMEOUT should be accepted\n"); + + if (!is_object($db = new PDO($dsn, $user, $pass, array(PDO::ATTR_TIMEOUT => -PHP_INT_MAX)))) + printf("[008] ATTR_TIMEOUT should be accepted\n"); + + /* TODO: Its ugly that PDO::ATTR_EMULATE_PREPARES == PDO::MYSQL_ATTR_DIRECT_QUERY */ + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => true)); + if (!is_object($db)) + printf("[009] ATTR_EMULATE_PREPARES should be accepted and on\n"); + if (!$db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) + printf("[010] [TODO][CHANGEREQUEST] ATTR_EMULATE_PREPARES should be on\n"); + if (!$db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[011] As PDO::MYSQL_ATTR_DIRECT_QUERY == PDO::ATTR_EMULATE_PREPARES + and PDO::ATTR_EMULATE_PREPARES overrules the other, PDO::MYSQL_ATTR_DIRECT_QUERY should be on\n"); + + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false)); + if (!is_object($db)) + printf("[012] ATTR_EMULATE_PREPARES should be accepted and on\n"); + if ($db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) + printf("[013] [TODO][CHANGEREQUEST] ATTR_EMULATE_PREPARES should be off\n"); + if ($db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[014] As PDO::MYSQL_ATTR_DIRECT_QUERY == PDO::ATTR_EMULATE_PREPARES + and PDO::ATTR_EMULATE_PREPARES overrules the other, PDO::MYSQL_ATTR_DIRECT_QUERY should be off\n"); + + // PDO::ATTR_EMULATE_PREPARES overrules PDO::MYSQL_ATTR_DIRECT_QUERY + // TODO: is it clever that a generic setting overrules a specific setting? + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => true, PDO::MYSQL_ATTR_DIRECT_QUERY => false)); + if (!$db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) + printf("[015] PDO::ATTR_EMULATE_PREPARES should be on\n"); + if (!$db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[016] PDO::MYSQL_ATTR_DIRECT_QUERY should be on\n"); + + $db = new PDO($dsn, $user, $pass, array(PDO::ATTR_EMULATE_PREPARES => false, PDO::MYSQL_ATTR_DIRECT_QUERY => true)); + if ($db->getAttribute(PDO::ATTR_EMULATE_PREPARES)) + printf("[017] PDO::ATTR_EMULATE_PREPARES should be off\n"); + if ($db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[018] PDO::MYSQL_ATTR_DIRECT_QUERY should be off\n"); + + set_option_and_check(19, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1, 'PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'); + set_option_and_check(20, PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0, 'PDO::MYSQL_ATTR_USE_BUFFERED_QUERY'); + + set_option_and_check(21, PDO::MYSQL_ATTR_LOCAL_INFILE, true, 'PDO::MYSQL_ATTR_LOCAL_INFILE'); + set_option_and_check(22, PDO::MYSQL_ATTR_LOCAL_INFILE, false, 'PDO::MYSQL_ATTR_LOCAL_INFILE'); + + set_option_and_check(23, PDO::MYSQL_ATTR_INIT_COMMAND, 'SET @a=1', 'PDO::MYSQL_ATTR_INIT_COMMAND'); + set_option_and_check(24, PDO::MYSQL_ATTR_INIT_COMMAND, '', 'PDO::MYSQL_ATTR_INIT_COMMAND'); + set_option_and_check(25, PDO::MYSQL_ATTR_INIT_COMMAND, 'INSERT INTO nonexistent(invalid) VALUES (1)', 'PDO::MYSQL_ATTR_INIT_COMMAND'); + + set_option_and_check(33, PDO::MYSQL_ATTR_DIRECT_QUERY, 1, 'PDO::MYSQL_ATTR_DIRECT_QUERY'); + set_option_and_check(34, PDO::MYSQL_ATTR_DIRECT_QUERY, 0, 'PDO::MYSQL_ATTR_DIRECT_QUERY'); + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + (is_object($db)) ? $db->errorCode() : 'n/a', + (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options.php.expectf new file mode 100644 index 000000000..4cb83591a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options.php.expectf @@ -0,0 +1,16 @@ +[003] [TODO][CHANGEREQUEST] Please, lets not ignore invalid options and bail out! +[003a] Expecting default value for 'PDO::ATTR_EMULATE_PREPARES' of '1'/integer, getAttribute() reports setting ''/boolean +[003a] Expecting default value for 'PDO::MYSQL_ATTR_INIT_COMMAND' of ''/string, getAttribute() reports setting ''/boolean +HipHop Warning: %a +[010] [TODO][CHANGEREQUEST] ATTR_EMULATE_PREPARES should be on +HipHop Warning: %a +HipHop Warning: %a +[015] PDO::ATTR_EMULATE_PREPARES should be on +[016] PDO::MYSQL_ATTR_DIRECT_QUERY should be on +HipHop Warning: %a +[018] PDO::MYSQL_ATTR_DIRECT_QUERY should be off +[021] Execting '1'/boolean got ''/boolean' for options 'PDO::MYSQL_ATTR_LOCAL_INFILE' +[023] Execting 'SET @a=1'/string got ''/boolean' for options 'PDO::MYSQL_ATTR_INIT_COMMAND' +[024] SQLSTATE[42000] [1065] Query was empty +[025] SQLSTATE[42S02] [1146] Table '%s.nonexistent' doesn't exist +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options_libmysql.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options_libmysql.php new file mode 100644 index 000000000..bf76e2d43 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options_libmysql.php @@ -0,0 +1,68 @@ + $value)); + if (!is_object($db) || (!$ignore_diff && ($value !== ($tmp = @$db->getAttribute($option))))) + printf("[%03d] Execting '%s'/%s got '%s'/%s' for options '%s'\n", + $offset, + $value, gettype($value), + $tmp, gettype($tmp), + $option_desc); + } catch (PDOException $e) { + printf("[%03d] %s\n", $offset, $e->getMessage()); + } + + } + + try { + + $dsn = MySQLPDOTest::getDSN(); + $user = PDO_MYSQL_TEST_USER; + $pass = PDO_MYSQL_TEST_PASS; + + $valid_options = array(); + $valid_options[PDO::MYSQL_ATTR_MAX_BUFFER_SIZE] = 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE'; + $valid_options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'PDO::MYSQL_ATTR_INIT_COMMAND'; + $valid_options[PDO::MYSQL_ATTR_READ_DEFAULT_FILE] = 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE'; + $valid_options[PDO::MYSQL_ATTR_READ_DEFAULT_GROUP] = 'PDO::MYSQL_ATTR_READ_DEFAULT_GROUP'; + + $defaults[PDO::MYSQL_ATTR_MAX_BUFFER_SIZE] = 1048576; + /* TODO getAttribute() does not handle it */ + $defaults[PDO::MYSQL_ATTR_INIT_COMMAND] = ''; + $defaults[PDO::MYSQL_ATTR_READ_DEFAULT_FILE] = false; + $defaults[PDO::MYSQL_ATTR_READ_DEFAULT_GROUP] = false; + + $db = new PDO($dsn, $user, $pass); + foreach ($valid_options as $option => $name) { + /* TODO getAttribute() is pretty poor in supporting the options, suppress errors */ + $tmp = @$db->getAttribute($option); + if ($tmp !== $defaults[$option]) + printf("[001] Expecting default value for '%s' of '%s'/%s, getAttribute() reports setting '%s'/%s\n", + $name, $defaults[$option], gettype($defaults[$option]), + $tmp, gettype($tmp)); + } + + set_option_and_check(26, PDO::MYSQL_ATTR_READ_DEFAULT_FILE, true, 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE'); + set_option_and_check(27, PDO::MYSQL_ATTR_READ_DEFAULT_FILE, false, 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE'); + + set_option_and_check(30, PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, -1, 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE', true); + set_option_and_check(31, PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, PHP_INT_MAX, 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE'); + set_option_and_check(32, PDO::MYSQL_ATTR_MAX_BUFFER_SIZE, 1, 'PDO::MYSQL_ATTR_MAX_BUFFER_SIZE'); + + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + (is_object($db)) ? $db->errorCode() : 'n/a', + (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options_libmysql.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options_libmysql.php.expectf new file mode 100644 index 000000000..22395ffe9 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_options_libmysql.php.expectf @@ -0,0 +1,3 @@ +[001] Expecting default value for 'PDO::MYSQL_ATTR_INIT_COMMAND' of ''/string, getAttribute() reports setting ''/boolean +[026] Execting '1'/boolean got ''/boolean' for options 'PDO::MYSQL_ATTR_READ_DEFAULT_FILE' +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_uri.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_uri.php new file mode 100644 index 000000000..d0fb60558 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_uri.php @@ -0,0 +1,60 @@ +getMessage()); + } + unlink($file); + } + + if ($fp = @fopen($file, 'w')) { + fwrite($fp, sprintf('mysql:dbname=letshopeinvalid;%s%s', + chr(0), $dsn)); + fclose($fp); + clearstatcache(); + assert(file_exists($file)); + try { + $db = new PDO($uri, $user, $pass); + } catch (PDOException $e) { + printf("[003] URI=%s, DSN=%s, File=%s (%d bytes, '%s'), chr(0) test, %s\n", + $uri, $dsn, + $file, filesize($file), file_get_contents($file), + $e->getMessage()); + } + unlink($file); + } + + } + + /* TODO: safe mode */ + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + (is_object($db)) ? $db->errorCode() : 'n/a', + (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_uri.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_uri.php.expectf new file mode 100644 index 000000000..e30b276cd --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql___construct_uri.php.expectf @@ -0,0 +1,5 @@ +HipHop Warning: %a +[002] URI=uri:file:%spdomuri.tst, DSN=mysql%sdbname=%s, File=%spdomuri.tst (%d bytes, 'mysql%sdbname=%s'), invalid data source URI +HipHop Warning: %a +[003] URI=uri:file:%spdomuri.tst, DSN=mysql%sdbname=%s, File=%spdomuri.tst (%d bytes, 'mysql%sdbname=letshopeinvalid%s'), chr(0) test, invalid data source URI +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_autocommit.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_autocommit.php new file mode 100644 index 000000000..a66f640fd --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_autocommit.php @@ -0,0 +1,84 @@ +getAttribute(PDO::ATTR_AUTOCOMMIT))) + printf("[001] Expecting int/1 got %s\n", var_export($tmp, true)); + + // lets see if the server agrees to that + $row = $db->query('SELECT @@autocommit AS _autocommit')->fetch(PDO::FETCH_ASSOC); + if (!$row['_autocommit']) + printf("[002] Server autocommit mode should be on, got '%s'\n", var_export($row['_autocommit'])); + + // on -> off + if (!$db->setAttribute(PDO::ATTR_AUTOCOMMIT, 0)) + printf("[003] Cannot turn off autocommit\n"); + + $row = $db->query('SELECT @@autocommit AS _autocommit')->fetch(PDO::FETCH_ASSOC); + if ($row['_autocommit']) + printf("[004] Server autocommit mode should be off, got '%s'\n", var_export($row['_autocommit'])); + + // PDO thinks autocommit is off, but its manually turned on... + if (!$db->query('SET autocommit = 1')) + printf("[005] Cannot turn on server autocommit mode, %s\n", var_export($db->errorInfo(), true)); + + if (0 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT))) + printf("[006] Expecting int/0 got %s\n", var_export($tmp, true)); + + // off -> on + if (!$db->query('SET autocommit = 0')) + printf("[007] Cannot turn off server autocommit mode, %s\n", var_export($db->errorInfo(), true)); + + if (!$db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1)) + printf("[008] Cannot turn on autocommit\n"); + + $row = $db->query('SELECT @@autocommit AS _autocommit')->fetch(PDO::FETCH_ASSOC); + if (!$row['_autocommit']) + printf("[009] Server autocommit mode should be on, got '%s'\n", var_export($row['_autocommit'])); + + if (1 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT))) + printf("[010] Expecting int/1 got %s\n", var_export($tmp, true)); + + if (MySQLPDOTest::detect_transactional_mysql_engine($db)) { + // nice, we have a transactional engine to play with + + MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + $num = $row['_num']; + + $db->query("INSERT INTO test(id, label) VALUES (100, 'z')"); + $num++; + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[011] Insert has failed, test will fail\n"); + + // autocommit is on, no rollback possible + $db->query('ROLLBACK'); + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[012] ROLLBACK should not have undone anything\n"); + + if (!$db->setAttribute(PDO::ATTR_AUTOCOMMIT, 0)) + printf("[013] Cannot turn off autocommit\n"); + + $db->query('DELETE FROM test WHERE id = 100'); + $db->query('ROLLBACK'); + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[014] ROLLBACK should have undone the DELETE\n"); + + $db->query('DELETE FROM test WHERE id = 100'); + $db->query('COMMIT'); + $num--; + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[015] DELETE should have been committed\n"); + + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_autocommit.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_autocommit.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_autocommit.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_case.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_case.php new file mode 100644 index 000000000..935de5a03 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_case.php @@ -0,0 +1,79 @@ +getAttribute(PDO::ATTR_CASE); + $known = array( + PDO::CASE_LOWER => 'PDO::CASE_LOWER', + PDO::CASE_UPPER => 'PDO::CASE_UPPER', + PDO::CASE_NATURAL => 'PDO::CASE_NATURAL' + ); + if (!isset($known[$default])) + printf("[001] getAttribute(PDO::ATTR_CASE) returns unknown value '%s'\n", + var_export($default, true)); + else + var_dump($known[$default]); + + // lets see what the default is... + if (!is_object($stmt = $db->query("SELECT id, id AS 'ID_UPPER', label FROM test ORDER BY id ASC LIMIT 2"))) + printf("[002] %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + var_dump($stmt->fetchAll(PDO::FETCH_BOTH)); + + if (true !== $db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER)) + printf("[003] Cannot set PDO::ATTR_CASE = PDO::CASE_LOWER, %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + if (($tmp = $db->getAttribute(PDO::ATTR_CASE)) !== PDO::CASE_LOWER) + printf("[004] getAttribute(PDO::ATTR_CASE) returns wrong value '%s'\n", + var_export($tmp, true)); + + if (true === $db->exec('ALTER TABLE test ADD MiXeD CHAR(1)')) + printf("[005] Cannot add column %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + if (false === $db->exec('ALTER TABLE test ADD MYUPPER CHAR(1)')) + printf("[006] Cannot add column %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + if (!is_object($stmt = $db->query("SELECT id, id AS 'ID_UPPER', label, MiXeD, MYUPPER FROM test ORDER BY id ASC LIMIT 2"))) + printf("[007] %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + var_dump($stmt->fetchAll(PDO::FETCH_BOTH)); + + if (true !== $db->setAttribute(PDO::ATTR_CASE, PDO::CASE_UPPER)) + printf("[008] Cannot set PDO::ATTR_CASE = PDO::CASE_UPPER %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + if (($tmp = $db->getAttribute(PDO::ATTR_CASE)) !== PDO::CASE_UPPER) + printf("[009] getAttribute(PDO::ATTR_CASE) returns wrong value '%s'\n", + var_export($tmp, true)); + + if (!is_object($stmt = $db->query("SELECT id, label, MiXeD, MYUPPER, MYUPPER AS 'lower' FROM test ORDER BY id ASC LIMIT 1"))) + printf("[010] %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + var_dump($stmt->fetchAll(PDO::FETCH_BOTH)); + + if (true !== $db->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL)) + printf("[011] Cannot set PDO::ATTR_CASE = PDO::CASE_NATURAL %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + if (($tmp = $db->getAttribute(PDO::ATTR_CASE)) !== PDO::CASE_NATURAL) + printf("[012] getAttribute(PDO::ATTR_CASE) returns wrong value '%s'\n", + var_export($tmp, true)); + + if (!is_object($stmt = $db->query("SELECT id, label, MiXeD, MYUPPER, id AS 'ID' FROM test ORDER BY id ASC LIMIT 1"))) + printf("[013] %s - %s\n", + var_export($db->errorInfo(), true), var_export($db->errorCode(), true)); + + var_dump($stmt->fetchAll(PDO::FETCH_BOTH)); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_case.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_case.php.expectf new file mode 100644 index 000000000..7155f671f --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_case.php.expectf @@ -0,0 +1,132 @@ +%unicode|string%(15) "PDO::CASE_LOWER" +array(2) { + [0]=> + array(6) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [0]=> + %unicode|string%(1) "1" + [%u|b%"id_upper"]=> + %unicode|string%(1) "1" + [1]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + [2]=> + %unicode|string%(1) "a" + } + [1]=> + array(6) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [0]=> + %unicode|string%(1) "2" + [%u|b%"id_upper"]=> + %unicode|string%(1) "2" + [1]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(1) "b" + [2]=> + %unicode|string%(1) "b" + } +} +array(2) { + [0]=> + array(10) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [0]=> + %unicode|string%(1) "1" + [%u|b%"id_upper"]=> + %unicode|string%(1) "1" + [1]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + [2]=> + %unicode|string%(1) "a" + [%u|b%"mixed"]=> + NULL + [3]=> + NULL + [%u|b%"myupper"]=> + NULL + [4]=> + NULL + } + [1]=> + array(10) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [0]=> + %unicode|string%(1) "2" + [%u|b%"id_upper"]=> + %unicode|string%(1) "2" + [1]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(1) "b" + [2]=> + %unicode|string%(1) "b" + [%u|b%"mixed"]=> + NULL + [3]=> + NULL + [%u|b%"myupper"]=> + NULL + [4]=> + NULL + } +} +array(1) { + [0]=> + array(10) { + [%u|b%"ID"]=> + %unicode|string%(1) "1" + [0]=> + %unicode|string%(1) "1" + [%u|b%"LABEL"]=> + %unicode|string%(1) "a" + [1]=> + %unicode|string%(1) "a" + [%u|b%"MIXED"]=> + NULL + [2]=> + NULL + [%u|b%"MYUPPER"]=> + NULL + [3]=> + NULL + [%u|b%"LOWER"]=> + NULL + [4]=> + NULL + } +} +array(1) { + [0]=> + array(10) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [0]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + [1]=> + %unicode|string%(1) "a" + [%u|b%"MiXeD"]=> + NULL + [2]=> + NULL + [%u|b%"MYUPPER"]=> + NULL + [3]=> + NULL + [%u|b%"ID"]=> + %unicode|string%(1) "1" + [4]=> + %unicode|string%(1) "1" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_client_version.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_client_version.php new file mode 100644 index 000000000..a9167617e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_client_version.php @@ -0,0 +1,25 @@ +errorCode()) || ('00000' == $db->errorCode())); + + $version = $db->getAttribute(PDO::ATTR_CLIENT_VERSION); + + // No more constraints - mysqlnd and libmysql return different strings at least + // with mysqli. Return type check is already performed in the generic test. + // According to the manual we should get an int but as of today we do get a string... + if ('' == $version) + printf("[001] Client version must not be empty\n"); + + + // Read-only + if (false !== $db->setAttribute(PDO::ATTR_CLIENT_VERSION, '1.0')) + printf("[002] Wonderful, I can change the client version!\n"); + + $new_version = $db->getAttribute(PDO::ATTR_CLIENT_VERSION); + if ($new_version !== $version) + printf("[003] Did we change it from '%s' to '%s'?\n", $version, $new_version); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_client_version.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_client_version.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_client_version.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_connection_status.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_connection_status.php new file mode 100644 index 000000000..f89d60b1e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_connection_status.php @@ -0,0 +1,25 @@ +getAttribute(PDO::ATTR_CONNECTION_STATUS); + if (ini_get('unicode.semantics')) { + if (!is_unicode($status)) + printf("[001] Expecting unicode, got '%s'\n", var_export($status, true)); + } else { + if (!is_string($status)) + printf("[002] Expecting string, got '%s'\n", var_export($status, true)); + } + + if ('' == $status) + printf("[003] Connection status string must not be empty\n"); + + if (false !== $db->setAttribute(PDO::ATTR_CONNECTION_STATUS, 'my own connection status')) + printf("[004] Changing read only attribute\n"); + + $status2 = $db->getAttribute(PDO::ATTR_CONNECTION_STATUS); + if ($status !== $status2) + printf("[005] Connection status should not have changed\n"); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_connection_status.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_connection_status.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_connection_status.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_driver_name.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_driver_name.php new file mode 100644 index 000000000..22e0b89e3 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_driver_name.php @@ -0,0 +1,18 @@ +errorCode()) || ('00000' == $db->errorCode())); + + $name = $db->getAttribute(PDO::ATTR_DRIVER_NAME); + var_dump($name); + + if (false !== $db->setAttribute(PDO::ATTR_DRIVER_NAME, 'mydriver')) + printf("[001] Wonderful, I can create new PDO drivers!\n"); + + $new_name = $db->getAttribute(PDO::ATTR_DRIVER_NAME); + if ($name != $new_name) + printf("[002] Did we change it from '%s' to '%s'?\n", $name, $new_name); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_driver_name.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_driver_name.php.expectf new file mode 100644 index 000000000..a3e888d7a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_driver_name.php.expectf @@ -0,0 +1,2 @@ +%unicode|string%(5) "mysql" +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_fetch_table_names.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_fetch_table_names.php new file mode 100644 index 000000000..5b721b6f4 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_fetch_table_names.php @@ -0,0 +1,17 @@ +setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, 1); + $stmt = $db->query('SELECT label FROM test LIMIT 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt->closeCursor(); + + $db->setAttribute(PDO::ATTR_FETCH_TABLE_NAMES, 0); + $stmt = $db->query('SELECT label FROM test LIMIT 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt->closeCursor(); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_fetch_table_names.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_fetch_table_names.php.expectf new file mode 100644 index 000000000..d46ed50f9 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_fetch_table_names.php.expectf @@ -0,0 +1,15 @@ +array(1) { + [0]=> + array(1) { + [%u|b%"test.label"]=> + %unicode|string%(1) "a" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_max_buffer_size.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_max_buffer_size.php new file mode 100644 index 000000000..64aff8901 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_max_buffer_size.php @@ -0,0 +1,58 @@ + $buffer_size, + /* buffer is only relevant with native PS */ + PDO::MYSQL_ATTR_DIRECT_QUERY => 0, + PDO::ATTR_EMULATE_PREPARES => 0, + )); + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, val LONGBLOB) ENGINE = %s', PDO_MYSQL_TEST_ENGINE)); + + // 10 * (10 * 1024) = 10 * (10 * 1k) = 100k + $db->exec('INSERT INTO test(id, val) VALUES (1, REPEAT("01234567890", 10240))'); + + $stmt = $db->prepare('SELECT id, val FROM test'); + $stmt->execute(); + + $id = $val = NULL; + $stmt->bindColumn(1, $id); + $stmt->bindColumn(2, $val); + while ($row = $stmt->fetch(PDO::FETCH_BOUND)) { + printf("[%03d] id = %d, val = %s... (length: %d)\n", + $offset, $id, substr($val, 0, 10), strlen($val)); + } + $db->exec('DROP TABLE IF EXISTS test'); + + } catch (PDOException $e) { + printf("[%03d] %s, [%s] %s\n", + $offset, + $e->getMessage(), + (is_object($db)) ? $db->errorCode() : 'n/a', + (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + } + + try_buffer_size(1, -1); + try_buffer_size(2, 1000); + try_buffer_size(3, NULL); + try_buffer_size(4, 2000); + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_max_buffer_size.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_max_buffer_size.php.expectf new file mode 100644 index 000000000..737744aeb --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_max_buffer_size.php.expectf @@ -0,0 +1,5 @@ +[001] id = 1, val = 0123456789... (length: %d) +[002] id = 1, val = 0123456789... (length: 1000) +[003] id = 1, val = 0123456789... (length: %d) +[004] id = 1, val = 0123456789... (length: 2000) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_oracle_nulls.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_oracle_nulls.php new file mode 100644 index 000000000..0709ccbff --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_oracle_nulls.php @@ -0,0 +1,74 @@ +setAttribute(PDO::ATTR_ORACLE_NULLS, $tmp)) + printf("[001] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...\n"); + + $tmp = new stdClass(); + if (false !== @$db->setAttribute(PDO::ATTR_ORACLE_NULLS, $tmp)); + printf("[002] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...\n"); + + if (false !== @$db->setAttribute(PDO::ATTR_ORACLE_NULLS, 'pdo')) + printf("[003] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS...\n"); + + $db->setAttribute(PDO::ATTR_ORACLE_NULLS, 1); + $stmt = $db->query("SELECT NULL AS z, '' AS a, ' ' AS b, TRIM(' ') as c, ' d' AS d, '" . chr(0) . " e' AS e"); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $db->setAttribute(PDO::ATTR_ORACLE_NULLS, 0); + $stmt = $db->query("SELECT NULL AS z, '' AS a, ' ' AS b, TRIM(' ') as c, ' d' AS d, '" . chr(0) . " e' AS e"); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $db->setAttribute(PDO::ATTR_ORACLE_NULLS, 1); + $stmt = $db->query('SELECT VERSION() as _version'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if ((int)substr($row['_version'], 0, 1) >= 5) + $have_procedures = true; + else + $have_procedures = false; + + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + + if ($have_procedures && (false !== $db->exec('DROP PROCEDURE IF EXISTS p')) && + (false !== $db->exec("CREATE PROCEDURE p() BEGIN SELECT NULL as z, '' AS a, ' ' AS b, TRIM(' ') as c, ' d' AS d, ' e' AS e; END;"))) { + // requires MySQL 5+ + $stmt = $db->prepare('CALL p()'); + $stmt->execute(); + $expected = array( + array( + "z" => NULL, + "a" => NULL, + "b" => " ", + "c" => NULL, + "d" => " d", + "e" => " e", + ), + ); + do { + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if ($tmp != $expected) { + printf("[004] Expecting %s got %s\n", + var_export($expected, true), var_export($tmp, true)); + } + } while ($stmt->nextRowset()); + + $stmt->execute(); + do { + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if ($tmp != $expected) { + printf("[005] Expecting %s got %s\n", + var_export($expected, true), var_export($tmp, true)); + } + } while ($stmt->nextRowset()); + + } + + if ($have_procedures) + @$db->exec('DROP PROCEDURE IF EXISTS p'); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_oracle_nulls.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_oracle_nulls.php.expectf new file mode 100644 index 000000000..84e4b9ccf --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_oracle_nulls.php.expectf @@ -0,0 +1,37 @@ +[002] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS... +[003] Maybe PDO could indicate that this is not a proper way of setting ATTR_ORACLE_NULLS... +array(1) { + [0]=> + array(6) { + [%u|b%"z"]=> + NULL + [%u|b%"a"]=> + NULL + [%u|b%"b"]=> + %unicode|string%(1) " " + [%u|b%"c"]=> + NULL + [%u|b%"d"]=> + %unicode|string%(2) " d" + [%u|b%"e"]=> + %unicode|string%(3) "%se" + } +} +array(1) { + [0]=> + array(6) { + [%u|b%"z"]=> + NULL + [%u|b%"a"]=> + %unicode|string%(0) "" + [%u|b%"b"]=> + %unicode|string%(1) " " + [%u|b%"c"]=> + %unicode|string%(0) "" + [%u|b%"d"]=> + %unicode|string%(2) " d" + [%u|b%"e"]=> + %unicode|string%(3) "%se" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_prefetch.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_prefetch.php new file mode 100644 index 000000000..9a23e0313 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_prefetch.php @@ -0,0 +1,6 @@ +getAttribute(PDO::ATTR_PREFETCH)); + var_dump($db->setAttribute(PDO::ATTR_PREFETCH, true)); + print "done!"; \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_prefetch.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_prefetch.php.expectf new file mode 100644 index 000000000..a0782176f --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_prefetch.php.expectf @@ -0,0 +1,4 @@ +HipHop Warning: %a +bool(false) +bool(false) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_info.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_info.php new file mode 100644 index 000000000..a4d18a0e4 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_info.php @@ -0,0 +1,36 @@ +errorCode()) || ('00000' == $db->errorCode())); + + $info = $db->getAttribute(PDO::ATTR_SERVER_INFO); + if ('' == $info) + printf("[001] Server info must not be empty\n"); + + // Read-only? + if (false !== $db->setAttribute(PDO::ATTR_SERVER_INFO, 'new uptime: 0s')) + printf("[002] Wonderful, I can change the client version!\n"); + + $new_info = $db->getAttribute(PDO::ATTR_SERVER_INFO); + if (soundex($new_info) != soundex($info)) + printf("[003] Did we change it from '%s' to '%s'?\n", $info, $info); + + // lets hope we always run this in the same second as we did run the server info request... + if (!$stmt = $db->query("SHOW STATUS LIKE '%uptime%'")) + printf("[004] Cannot run SHOW STATUS, [%s]\n", $db->errorCode()); + else { + if (!$row = $stmt->fetch(PDO::FETCH_NUM)) + printf("[005] Unable to fetch uptime, [%s]\n", $db->errorCode()); + else + $uptime = $row[1]; + $stmt->closeCursor(); + } + + if (!preg_match('/Uptime/i', $info)) + printf("[006] Can't find uptime in server info '%s'\n", $info); + + if (isset($uptime) && !preg_match(sprintf('/Uptime: %d/i', $uptime), $info)) + printf("[007] SHOW STATUS and server info have reported a different uptime, please check. Server info: '%s', SHOW STATUS: '%s'\n", $info, $uptime); + + print "done!"; \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_info.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_info.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_info.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_version.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_version.php new file mode 100644 index 000000000..b828cc627 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_version.php @@ -0,0 +1,53 @@ +errorCode()) || ('00000' == $db->errorCode())); + + $version = $db->getAttribute(PDO::ATTR_SERVER_VERSION); + if ('' == $version) + printf("[001] Server version must not be empty\n"); + + // Ideally the server version would be an integer - as documented but BC break! + // If its a version string it should be of the format \d+\.\d+\.\d+.* + + if (is_string($version)) { + // Its not an int like documented but a string - maybe for BC reasons... + if (!preg_match('/(\d+)\.(\d+)\.(\d+)(.*)/', $version, $matches)) + printf("[002] Client version string seems wrong, got '%s'\n", $version); + else { + // Difficult to define any meaningful constraints + // A possible better check would be calling mysqli_get_server_version() and + // comparing what we get. However, mysqli_get_server_version() needs a mysqli handle + // for which in turn one needs to parse the PDO test environment variables + // for connection parameter... + if ($matches[1] < 3) + printf("[003] Strange major version: '%s'. Should be more than 3\n", $matches[1]); + if ($matches[2] < 0) + printf("[004] Minor version should be at least 0, got '%s'\n", $matches[2]); + if ($matches[3] < 0) + printf("[005] Sub version should be at least 0, got '%s'\n", $matches[2]); + } + } else if (is_int($version)) { + // Lets accept also int if it follows the rules from the original MYSQL C API + $major = floor($version / 10000); + $minor = floor(($version - ($main * 10000)) / 100); + $sub = $version - ($main * 10000) - ($minor * 100); + if ($major < 3) + printf("[006] Strange major version: '%s'. Should be more than 3\n", $major); + if ($minor < 0) + printf("[007] Minor version should be at least 0, got '%s'\n", $minor); + if ($sub < 0) + printf("[008] Sub version should be at least 0, got '%s'\n", $sub); + } + + // Read-only? + if (false !== $db->setAttribute(PDO::ATTR_CLIENT_VERSION, '1.0')) + printf("[009] Wonderful, I can change the client version!\n"); + + $new_version = $db->getAttribute(PDO::ATTR_SERVER_VERSION); + if ($new_version !== $version) + printf("[010] Did we change it from '%s' to '%s'?\n", $version, $new_version); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_version.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_version.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_server_version.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_statement_class.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_statement_class.php new file mode 100644 index 000000000..8649f9ec0 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_statement_class.php @@ -0,0 +1,99 @@ +getAttribute(PDO::ATTR_STATEMENT_CLASS); + var_dump($default); + + if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS))) + printf("[001] Expecting boolean/false got %s\n", var_export($tmp, true)); + + if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, 'foo'))) + printf("[002] Expecting boolean/false got %s\n", var_export($tmp, true)); + + if (false !== ($tmp = @$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('classname')))) + printf("[003] Expecting boolean/false got %s\n", var_export($tmp, true)); + + // unknown class + if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('classname', array())))) + printf("[004] Expecting boolean/false got %s\n", var_export($tmp, true)); + + // class not derived from PDOStatement + class myclass { + function __construct() { + printf("myclass\n"); + } + } + if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('myclass', array())))) + printf("[005] Expecting boolean/false got %s\n", var_export($tmp, true)); + + // public constructor not allowed + class mystatement extends PDOStatement { + public function __construct() { + printf("mystatement\n"); + } + } + + if (false !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement', array())))) + printf("[006] Expecting boolean/false got %s\n", var_export($tmp, true)); + + // ... but a public destructor is allowed + class mystatement2 extends PDOStatement { + public function __destruct() { + printf("mystatement\n"); + } + } + + if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement2', array())))) + printf("[007] Expecting boolean/true got %s\n", var_export($tmp, true)); + + // private constructor + class mystatement3 extends PDOStatement { + private function __construct($msg) { + printf("mystatement3\n"); + var_dump($msg); + } + } + if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement3', array('param1'))))) + printf("[008] Expecting boolean/true got %s\n", var_export($tmp, true)); + + // private constructor + class mystatement4 extends PDOStatement { + private function __construct($msg) { + printf("%s\n", get_class($this)); + var_dump($msg); + } + } + if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement4', array('param1'))))) + printf("[008] Expecting boolean/true got %s\n", var_export($tmp, true)); + + var_dump($db->getAttribute(PDO::ATTR_STATEMENT_CLASS)); + $stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 2'); + + class mystatement5 extends mystatement4 { + public function fetchAll($fetch_style = 1, $column_index = 1, $ctor_args = array()) { + return "no data :)"; + } + } + + if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement5', array('mystatement5'))))) + printf("[009] Expecting boolean/true got %s\n", var_export($tmp, true)); + $stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 2'); + var_dump($stmt->fetchAll()); + + if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('PDOStatement')))) + printf("[010] Expecting boolean/true got %s\n", var_export($tmp, true)); + + $stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 1'); + var_dump($stmt->fetchAll()); + + // Yes, this is a fatal error and I want it to fail. + abstract class mystatement6 extends mystatement5 { + } + if (true !== ($tmp = $db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('mystatement6', array('mystatement6'))))) + printf("[011] Expecting boolean/true got %s\n", var_export($tmp, true)); + $stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 1'); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_statement_class.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_statement_class.php.expectf new file mode 100644 index 000000000..78533e354 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_attr_statement_class.php.expectf @@ -0,0 +1,38 @@ +array(1) { + [0]=> + %unicode|string%(12) "PDOStatement" +} +HipHop Warning: %a +HipHop Warning: %a +HipHop Warning: %a +HipHop Warning: %a +HipHop Warning: %a +HipHop Warning: %a +array(2) { + [0]=> + %unicode|string%(12) "mystatement4" + [1]=> + array(1) { + [0]=> + %unicode|string%(6) "param1" + } +} +mystatement4 +%unicode|string%(6) "param1" +mystatement5 +%unicode|string%(12) "mystatement5" +%unicode|string%(10) "no data :)" +array(1) { + [0]=> + array(4) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [0]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + [1]=> + %unicode|string%(1) "a" + } +} +HipHop Fatal error: %a \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_begintransaction.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_begintransaction.php new file mode 100644 index 000000000..2f4a3cc9a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_begintransaction.php @@ -0,0 +1,174 @@ +getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[001] Autocommit should be on by default\n"); + + if (false == $db->beginTransaction()) + printf("[002] Cannot start a transaction, [%s] [%s]\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[003] Autocommit should be on by default, beginTransaction() shall not impact it\n"); + + if (0 == $db->exec('DELETE FROM test')) + printf("[004] No rows deleted, can't be true.\n"); + + /* This is the PDO way to close a connection */ + $db = null; + $db = MySQLPDOTest::factory(); + + /* Autocommit was off - by definition. Commit was not issued. DELETE should have been rolled back. */ + if (!($stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC'))) + printf("[005] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $row = $stmt->fetch(PDO::FETCH_ASSOC); + var_dump($row); + + if (!$db->beginTransaction()) + printf("[006] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (1 !== $db->exec(sprintf('DELETE FROM test WHERE id = %d', $row['id']))) + printf("[007] DELETE should have indicated 1 deleted row, [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (!$db->commit()) + printf("[008] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[009] Autocommit should be on after commit()\n"); + + if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) + printf("[010] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + var_dump($stmt->fetch(PDO::FETCH_ASSOC)); + + if (!$db->beginTransaction()) + printf("[011] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $db->exec(sprintf("INSERT INTO test(id, label) VALUES (%d, 'z')", $row['id'])); + + if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) + printf("[012] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $new_row1 = $stmt->fetch(PDO::FETCH_ASSOC); + var_dump($new_row1); + + if (!$db->commit()) + printf("[013] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) + printf("[014] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $new_row2 = $stmt->fetch(PDO::FETCH_ASSOC); + if ($new_row1 != $new_row2) { + printf("[015] Results must not differ!\n"); + var_dump($new_row1); + var_dump($new_row2); + } + + if (!$db->beginTransaction()) + printf("[016] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (1 !== $db->exec(sprintf('DELETE FROM test WHERE id = %d', $row['id']))) + printf("[017] DELETE should have indicated 1 deleted row, [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (!$db->rollback()) + printf("[018] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[019] Autocommit should be on after rollback\n"); + + if (!($stmt = $db->query(sprintf('SELECT id, label FROM test WHERE id = %d', $row['id'])))) + printf("[020] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $new_row2 = $stmt->fetch(PDO::FETCH_ASSOC); + if ($new_row1 != $new_row2) { + printf("[021] Results must not differ!\n"); + var_dump($new_row1); + var_dump($new_row2); + } + + // now, lets check the server variables + if (!($stmt = $db->query('SELECT @@autocommit as auto_commit'))) + printf("[022] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + if ($tmp['auto_commit'] != 1) + printf("[023] MySQL Server should indicate autocommit mode, expecting 1, got '%s', [%d] %s\n", + $tmp['auto_commit'], $stmt->errorCode(), $stmt->errorInfo()); + + if (!$db->beginTransaction()) + printf("[024] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (!($stmt = $db->query('SELECT @@autocommit as auto_commit'))) + printf("[025] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + if ($tmp['auto_commit'] != 0) + printf("[026] Autocommit mode of the MySQL Server should be off, got '%s', [%d] %s\n", + $tmp['auto_commit'], $stmt->errorCode(), trim(implode(' ', $stmt->errorInfo()))); + + $db->commit(); + // Now we should be back to autocommit - we've issues a commit + if ($tmp['auto_commit'] != 1) + printf("[027] MySQL Server should indicate autocommit mode, expecting 1, got '%s', [%d] %s\n", + $tmp['auto_commit'], $stmt->errorCode(), $stmt->errorInfo()); + + // Turn off autocommit using a server variable + $db->exec('SET @@autocommit = 0'); + if (1 === $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[028] I'm confused, how can autocommit be on? Didn't I say I want to manually control transactions?\n"); + + if (!$db->beginTransaction()) + printf("[029] Cannot start a transaction, [%d] %s\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + try { + if (false !== $db->beginTransaction()) { + printf("[030] No false and no exception - that's wrong.\n"); + } + } catch (PDOException $e) { + assert($e->getMessage() != ''); + } + + // TODO: What about an engine that does not support transactions? + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db, 'MyISAM'); + + if (false == $db->beginTransaction()) + printf("[031] Cannot start a transaction, [%s] [%s]\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + if (1 !== $db->getAttribute(PDO::ATTR_AUTOCOMMIT)) + printf("[032] Autocommit should be on my default, beginTransaction() should not change that\n"); + + if (0 == $db->exec('DELETE FROM test')) + printf("[033] No rows deleted, can't be true.\n"); + + if (!$db->commit()) + printf("[034] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + if (false == $db->beginTransaction()) + printf("[035] Cannot start a transaction, [%s] [%s]\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + if (0 == $db->exec("INSERT INTO test(id, label) VALUES (1, 'a')")) + printf("[036] Cannot insert data, [%s] [%s]\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + // Should cause a Server warning but no error + if (!$db->rollback()) + printf("[037] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + var_dump($db->errorCode()); + + if (1 != $db->exec('DELETE FROM test')) + printf("[038] No rows deleted, can't be true.\n"); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_begintransaction.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_begintransaction.php.expectf new file mode 100644 index 000000000..3d5e698dd --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_begintransaction.php.expectf @@ -0,0 +1,17 @@ +array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" +} +bool(false) +array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "z" +} +[026] Autocommit mode of the MySQL Server should be off, got '1', [0] 00000 +[028] I'm confused, how can autocommit be on? Didn't I say I want to manually control transactions? +%unicode|string%(5) "00000" +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_bit.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_bit.php new file mode 100644 index 000000000..282ab6bdb --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_bit.php @@ -0,0 +1,42 @@ +exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); + @$db->exec($sql); + if ($db->errorCode() != 0) { + // not all MySQL Server versions and/or engines might support the type + return true; + } + + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (?, ?)'); + $stmt->bindValue(1, $offset); + $stmt->bindValue(2, $value); + if (!$stmt->execute()) { + printf("[%03d + 1] INSERT failed, %s\n", $offset, var_export($stmt->errorInfo(), true)); + return false; + } + $stmt = $db->query('SELECT id, label FROM test'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + var_dump($row); + var_dump($value); + + return true; + } + + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + + test_type($db, 20, 'BIT(8)', 1); + + echo "done!\n"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_bit.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_bit.php.expectf new file mode 100644 index 000000000..02d0753ee --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_bit.php.expectf @@ -0,0 +1,8 @@ +array(2) { + [%u|b%"id"]=> + %unicode|string%(2) "20" + [%u|b%"label"]=> + %unicode|string%(1) "1" +} +int(1) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_class_constants.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_class_constants.php new file mode 100644 index 000000000..39c234ae5 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_class_constants.php @@ -0,0 +1,76 @@ + true, + 'MYSQL_ATTR_LOCAL_INFILE' => true, + 'MYSQL_ATTR_DIRECT_QUERY' => true, + 'MYSQL_ATTR_FOUND_ROWS' => true, + 'MYSQL_ATTR_IGNORE_SPACE' => true, + 'MYSQL_ATTR_INIT_COMMAND' => true, + "MYSQL_ATTR_SSL_KEY" => true, + "MYSQL_ATTR_SSL_CERT" => true, + "MYSQL_ATTR_SSL_CA" => true, + "MYSQL_ATTR_SSL_CAPATH" => true, + "MYSQL_ATTR_SSL_CIPHER" => true, + "MYSQL_ATTR_COMPRESS" => true, + ); + + if (!MySQLPDOTest::isPDOMySQLnd()) { + $expected['MYSQL_ATTR_MAX_BUFFER_SIZE'] = true; + $expected['MYSQL_ATTR_READ_DEFAULT_FILE'] = true; + $expected['MYSQL_ATTR_READ_DEFAULT_GROUP'] = true; + } + + /* + TODO + + MYSQLI_OPT_CONNECT_TIMEOUT != PDO::ATTR_TIMEOUT (integer) + Sets the timeout value in seconds for communications with the database. + ^ Potential BUG, PDO::ATTR_TIMEOUT is used in pdo_mysql_handle_factory + + MYSQLI_SET_CHARSET_NAME -> DSN/charset= + ^ Undocumented and pitfall for ext/mysqli users + + Assorted mysqlnd settings missing + */ + $ref = new ReflectionClass('PDO'); + $constants = $ref->getConstants(); + $values = array(); + + foreach ($constants as $name => $value) + if (substr($name, 0, 11) == 'MYSQL_ATTR_') { + if (!isset($values[$value])) + $values[$value] = array($name); + else + $values[$value][] = $name; + + if (isset($expected[$name])) { + unset($expected[$name]); + unset($constants[$name]); + } + + } else { + unset($constants[$name]); + } + + if (!empty($constants)) { + printf("[001] Dumping list of unexpected constants\n"); + var_dump($constants); + } + + if (!empty($expected)) { + printf("[002] Dumping list of missing constants\n"); + var_dump($expected); + } + + if (!empty($values)) { + foreach ($values as $value => $constants) { + if (count($constants) > 1) { + printf("[003] Several constants share the same value '%s'\n", $value); + var_dump($constants); + } + } + } + + print "done!"; \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_class_constants.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_class_constants.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_class_constants.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_commit.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_commit.php new file mode 100644 index 000000000..de0e0080a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_commit.php @@ -0,0 +1,74 @@ +beginTransaction())) { + printf("[001] Expecting true, got %s/%s\n", gettype($tmp), $tmp); + } + + // DDL will issue an implicit commit + $db->exec(sprintf('DROP TABLE IF EXISTS test_commit')); + $db->exec(sprintf('CREATE TABLE test_commit(id INT) ENGINE=%s', MySQLPDOTest::detect_transactional_mysql_engine($db))); + if (true !== ($tmp = $db->commit())) { + printf("[002] No commit allowed? [%s] %s\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + // pdo_transaction_transitions should check this as well... + // ... just to be sure the most basic stuff really works we check it again... + if (1 !== ($tmp = $db->getAttribute(PDO::ATTR_AUTOCOMMIT))) + printf("[003] According to the manual we should be back to autocommit mode, got %s/%s\n", + gettype($tmp), var_export($tmp, true)); + + if (true !== ($tmp = $db->beginTransaction())) + printf("[004] Expecting true, got %s/%s\n", gettype($tmp), $tmp); + + $db->exec("INSERT INTO test(id, label) VALUES (100, 'z')"); + + if (true !== ($tmp = $db->commit())) + printf("[005] No commit allowed? [%s] %s\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + // a weak test without unicode etc. - lets leave that to dedicated tests + $stmt = $db->query('SELECT id, label FROM test WHERE id = 100'); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (!isset($rows[0]['label']) || ($rows[0]['label'] != 'z')) { + printf("[006] Record data is strange, dumping rows\n"); + var_dump($rows); + } + + // Ok, lets check MyISAM resp. any other non-transactional engine + // pdo_mysql_begin_transaction has more on this, quick check only + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db, 'MyISAM'); + + if (true !== ($tmp = $db->beginTransaction())) + printf("[007] Expecting true, got %s/%s\n", gettype($tmp), $tmp); + + $db->exec("INSERT INTO test(id, label) VALUES (100, 'z')"); + if (true !== ($tmp = $db->commit())) + printf("[008] No commit allowed? [%s] %s\n", + $db->errorCode(), implode(' ', $db->errorInfo())); + + // a weak test without unicode etc. - lets leave that to dedicated tests + $stmt = $db->query('SELECT id, label FROM test WHERE id = 100'); + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (!isset($rows[0]['label']) || ($rows[0]['label'] != 'z')) { + printf("[009] Record data is strange, dumping rows\n"); + var_dump($rows); + } + + } catch (PDOException $e) { + printf("[002] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!";exec('DROP TABLE IF EXISTS test_commit'); +MySQLPDOTest::dropTestTable($db); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_commit.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_commit.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_commit.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_connect_charset.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_connect_charset.php new file mode 100644 index 000000000..0574eca66 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_connect_charset.php @@ -0,0 +1,22 @@ +query("SHOW VARIABLES LIKE 'character_set_connection'")->fetchObject()->value; + + /* Make sure that we don't attempt to set the current character set to make this case useful */ + $new_charset = ($charset == 'latin1' ? 'ascii' : 'latin1'); + + /* Done with the original connection, create a second link to test the character set being defined */ + unset($link); + + $link = MySQLPDOTest::factory('PDO', false, null, Array('charset' => $new_charset)); + $conn_charset = $link->query("SHOW VARIABLES LIKE 'character_set_connection'")->fetchObject()->value; + + if ($charset !== $conn_charset) { + echo "done!\n"; + } else { + echo "failed!\n"; + } +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_connect_charset.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_connect_charset.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_connect_charset.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorcode.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorcode.php new file mode 100644 index 000000000..377f90260 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorcode.php @@ -0,0 +1,72 @@ +errorCode(); + if (($code != $expected) && (($expected != '00000') && ($code != ''))) { + printf("[%03d] Expecting error code '%s' got code '%s'\n", + $offset, $expected, $code); + } + + } + + try { + + /* + If you create a PDOStatement object through PDO->prepare() + or PDO->query() and invoke an error on the statement handle, + PDO->errorCode() will not reflect that error. You must call + PDOStatement->errorCode() to return the error code for an + operation performed on a particular statement handle. + */ + $code = $db->errorCode(); + check_error(2, $db); + + $stmt = $db->query('SELECT id, label FROM test'); + $stmt2 = &$stmt; + check_error(3, $db); + check_error(4, $stmt); + + $db->exec('DROP TABLE IF EXISTS test'); + @$stmt->execute(); + check_error(4, $db); + check_error(5, $stmt, '42S02'); + check_error(6, $stmt2, '42S02'); + + $db->exec('DROP TABLE IF EXISTS unknown'); + @$stmt = $db->query('SELECT id, label FROM unknown'); + check_error(7, $db, '42S02'); + + MySQLPDOTest::createTestTable($db); + $stmt = $db->query('SELECT id, label FROM test'); + check_error(8, $db); + check_error(9, $stmt); + + $db2 = &$db; + @$db->query('SELECT id, label FROM unknown'); + check_error(10, $db, '42S02'); + check_error(11, $db2, '42S02'); + check_error(12, $stmt); + check_error(13, $stmt2); + + // lets hope this is an invalid attribute code + $invalid_attr = -1 * PHP_INT_MAX + 3; + $tmp = @$db->getAttribute($invalid_attr); + check_error(14, $db, 'IM001'); + check_error(15, $db2, 'IM001'); + check_error(16, $stmt); + check_error(17, $stmt2); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorcode.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorcode.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorcode.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorinfo.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorinfo.php new file mode 100644 index 000000000..f4f109d2c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorinfo.php @@ -0,0 +1,91 @@ +errorInfo(); + $code = $info[0]; + + if (($code != $expected) && (($expected != '00000') && ($code != ''))) { + printf("[%03d] Expecting error code '%s' got code '%s'\n", + $offset, $expected, $code); + } + + if ($expected != '00000') { + if (!isset($info[1]) || $info[1] == '') + printf("[%03d] Driver-specific error code not set\n", $offset); + if (!isset($info[2]) || $info[2] == '') + printf("[%03d] Driver-specific error message.not set\n", $offset); + } + + } + + function pdo_mysql_errorinfo($db, $offset) { + + try { + + /* + If you create a PDOStatement object through PDO->prepare() + or PDO->query() and invoke an error on the statement handle, + PDO->errorCode() will not reflect that error. You must call + PDOStatement->errorCode() to return the error code for an + operation performed on a particular statement handle. + */ + $code = $db->errorCode(); + check_error($offset + 2, $db); + + $stmt = $db->query('SELECT id, label FROM test'); + $stmt2 = &$stmt; + check_error($offset + 3, $db); + check_error($offset + 4, $stmt); + + $db->exec('DROP TABLE IF EXISTS test'); + @$stmt->execute(); + check_error($offset + 5, $db); + check_error($offset + 6, $stmt, '42S02'); + check_error($offset + 7, $stmt2, '42S02'); + + @$stmt = $db->query('SELECT id, label FROM unknown'); + check_error($offset + 8, $db, '42S02'); + + MySQLPDOTest::createTestTable($db); + $stmt = $db->query('SELECT id, label FROM test'); + check_error($offset + 9, $db); + check_error($offset + 10, $stmt); + + $db2 = &$db; + $db->exec('DROP TABLE IF EXISTS unknown'); + @$db->query('SELECT id, label FROM unknown'); + check_error($offset + 11, $db, '42S02'); + check_error($offset + 12, $db2, '42S02'); + check_error($offset + 13, $stmt); + check_error($offset + 14, $stmt2); + + // lets hope this is an invalid attribute code + $invalid_attr = -1 * PHP_INT_MAX + 3; + $tmp = @$db->getAttribute($invalid_attr); + check_error($offset + 15, $db, 'IM001'); + check_error($offset + 16, $db2, 'IM001'); + check_error($offset + 17, $stmt); + check_error($offset + 18, $stmt2); + + } catch (PDOException $e) { + printf("[%03d] %s [%s] %s\n", + $offset + 19, $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + } + + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + printf("Emulated Prepared Statements...\n"); + pdo_mysql_errorinfo($db, 0); + + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + printf("Native Prepared Statements...\n"); + pdo_mysql_errorinfo($db, 20); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorinfo.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorinfo.php.expectf new file mode 100644 index 000000000..7eeacccc7 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_errorinfo.php.expectf @@ -0,0 +1,7 @@ +Emulated Prepared Statements... +[015] Driver-specific error code not set +[015] Driver-specific error message.not set +[016] Driver-specific error code not set +[016] Driver-specific error message.not set +Native Prepared Statements... +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec.php new file mode 100644 index 000000000..8017e7ba5 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec.php @@ -0,0 +1,169 @@ +exec($sql); + if (!is_null($exp) && ($ret !== $exp)) { + printf("[%03d] Expecting '%s'/%s got '%s'/%s when running '%s', [%s] %s\n", + $offset, $exp, gettype($exp), $ret, gettype($ret), $sql, + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + } catch (PDOException $e) { + printf("[%03d] '%s' has failed, [%s] %s\n", + $offset, $sql, $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return true; + } + + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); + + /* affected rows related */ + try { + + exec_and_count(2, $db, 'DROP TABLE IF EXISTS test', 0); + exec_and_count(3, $db, sprintf('CREATE TABLE test(id INT NOT NULL PRIMARY KEY, col1 CHAR(10)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE), 0); + exec_and_count(4, $db, "INSERT INTO test(id, col1) VALUES (1, 'a')", 1); + exec_and_count(5, $db, "INSERT INTO test(id, col1) VALUES (2, 'b'), (3, 'c')", 2); + exec_and_count(6, $db, "UPDATE test SET id = 4 WHERE id = 3", 1); + exec_and_count(7, $db, "INSERT INTO test(id, col1) VALUES (1, 'd') ON DUPLICATE KEY UPDATE id = 3", 2); + exec_and_count(8, $db, "UPDATE test SET id = 5 WHERE id = 5", 0); + exec_and_count(9, $db, "INSERT INTO test(id, col1) VALUES (5, 'e') ON DUPLICATE KEY UPDATE id = 6", 1); + exec_and_count(10, $db, "REPLACE INTO test(id, col1) VALUES (5, 'f')", 2); + exec_and_count(11, $db, "REPLACE INTO test(id, col1) VALUES (6, 'g')", 1); + exec_and_count(12, $db, 'DELETE FROM test WHERE id > 2', 4); + exec_and_count(13, $db, 'DROP TABLE test', 0); + exec_and_count(14, $db, 'SET @myvar = 1', 0); + + exec_and_count(15, $db, 'THIS IS NOT VALID SQL, I HOPE', false); + printf("[016] [%s] %s\n", $db->errorCode(), implode(' ', $db->errorInfo())); + + exec_and_count(36, $db, sprintf('CREATE TABLE test(id INT NOT NULL PRIMARY KEY, col1 CHAR(10)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE), 0); + exec_and_count(37, $db, "INSERT INTO test(id, col1) VALUES (1, 'a')", 1); + // Results may vary. Typically you will get 1. But the MySQL 5.1 manual states: Truncation operations do not return the number of deleted rows. + // Don't rely on any return value! + exec_and_count(38, $db, 'TRUNCATE TABLE test', NULL); + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + + /* CREATE, DROP, CALL SP and SF */ + if (MySQLPDOTest::getServerVersion($db) > 50000) { + // let's try to play with stored procedures + try { + $ignore_exception = true; + exec_and_count(18, $db, 'DROP PROCEDURE IF EXISTS p', 0); + exec_and_count(19, $db, 'CREATE PROCEDURE p(OUT ver_param VARCHAR(255)) BEGIN SELECT VERSION() INTO ver_param; END;', 0); + // we got this far without problems. If there's an issue from now on, its a failure + $ignore_exception = false; + exec_and_count(20, $db, 'CALL p(@version)', 0); + $stmt = $db->query('SELECT @version AS p_version'); + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (count($tmp) > 1 || !isset($tmp[0]['p_version'])) { + printf("[022] Data seems wrong, dumping\n"); + var_dump($tmp); + } else { + $p_version = $tmp[0]['p_version']; + } + + $stmt = $db->query('SELECT VERSION() AS _version'); + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (count($tmp) > 1 || !isset($tmp[0]['_version'])) { + printf("[023] Data seems wrong, dumping\n"); + var_dump($tmp); + } else { + if ($p_version !== $tmp[0]['_version']) { + printf("[024] Found different version strings, SP returned '%s'/%s, SELECT returned '%s'/%s\n", + $p_version, gettype($p_version), + $tmp[0]['_version'], gettype($tmp[0]['_version'])); + } + } + exec_and_count(25, $db, 'DROP PROCEDURE IF EXISTS p', 0); + + } catch (PDOException $e) { + // ignore it, we might not have sufficient permissions + if (!$ignore_exception) + printf("[021] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + // stored function + try { + $ignore_exception = true; + exec_and_count(27, $db, 'DROP FUNCTION IF EXISTS f', 0); + exec_and_count(28, $db, 'CREATE FUNCTION f( ver_param VARCHAR(255)) RETURNS VARCHAR(255) DETERMINISTIC RETURN ver_param;', 0); + // we got this far without problems. If there's an issue from now on, its a failure + $ignore_exception = false; + $stmt = $db->query('SELECT f(VERSION()) AS f_version'); + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (count($tmp) > 1 || !isset($tmp[0]['f_version'])) { + printf("[029] Data seems wrong, dumping\n"); + var_dump($tmp); + } else { + $f_version = $tmp[0]['f_version']; + } + $stmt = $db->query('SELECT VERSION() AS _version'); + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (count($tmp) > 1 || !isset($tmp[0]['_version'])) { + printf("[030] Data seems wrong, dumping\n"); + var_dump($tmp); + } else { + if ($f_version !== $tmp[0]['_version']) { + printf("[031] Found different version strings, SF returned '%s'/%s, SELECT returned '%s'/%s\n", + $f_version, gettype($f_version), + $tmp[0]['_version'], gettype($tmp[0]['_version'])); + } + } + exec_and_count(32, $db, 'DROP FUNCTION IF EXISTS f', 0); + + } catch (PDOException $e) { + // ignore it, we might not have sufficient permissions + if (!$ignore_exception) + printf("[026] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + } + + // multi query + try { + + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + $exp = 0; + + $tmp = @$db->exec(sprintf('DROP TABLE IF EXISTS test; CREATE TABLE test(id INT) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + if ($exp !== $tmp) + printf("[034] Expecting %s/%s got %s/%s, [%s] %s\n", + $exp, gettype($exp), + $tmp, gettype($tmp), + $db->errorCode(), var_export($db->errorInfo(), true)); + + // this is interesting: if we get sort of affected rows, what will happen now? + $tmp = @$db->exec('INSERT INTO test(id) VALUES (1); INSERT INTO test(id) VALUES (2)'); + printf("[035] With emulated PS it works but makes no sense given that exec() returns sort of affected rows...\n"); + + + } catch (PDOException $e) { + printf("[033] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec.php.expectf new file mode 100644 index 000000000..8246f8848 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec.php.expectf @@ -0,0 +1,4 @@ +HipHop Warning: %a +[016] [42000] 42000 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'THIS IS NOT VALID SQL, I HOPE' at line %d +[035] With emulated PS it works but makes no sense given that exec() returns sort of affected rows... +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_ddl.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_ddl.php new file mode 100644 index 000000000..c9dba1677 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_ddl.php @@ -0,0 +1,79 @@ +exec($sql); + else + $ret = $db->exec($sql); + + if ($ret !== $exp) { + printf("[%03d] Expecting '%s'/%s got '%s'/%s when running '%s', [%s] %s\n", + $offset, $exp, gettype($exp), $ret, gettype($ret), $sql, + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + } catch (PDOException $e) { + printf("[%03d] '%s' has failed, [%s] %s\n", + $offset, $sql, $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return true; + } + + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); + + /* affected rows related */ + try { + + @$db->exec('DROP DATABASE IF EXISTS pdo_exec_ddl'); + @$db->exec('DROP DATABASE IF EXISTS pdo_exec_ddl2'); + if (1 === @$db->exec('CREATE DATABASE pdo_exec_ddl')) { + // yippie - we can create databases etc. + exec_and_count(3, $db, 'ALTER DATABASE pdo_exec_ddl CHARACTER SET latin1', 1); + } + + exec_and_count(4, $db, 'DROP TABLE IF EXISTS pdo_exec_ddl', 0); + exec_and_count(5, $db, 'DROP TABLE IF EXISTS pdo_exec_ddl2', 0); + if (0 === $db->exec('CREATE TABLE pdo_exec_ddl(id INT, col1 CHAR(2))')) { + exec_and_count(5, $db, 'CREATE INDEX idx1 ON pdo_exec_ddl(id)', 0); + exec_and_count(6, $db, 'DROP INDEX idx1 ON pdo_exec_ddl', 0); + exec_and_count(7, $db, 'ALTER TABLE pdo_exec_ddl DROP id', 0); + exec_and_count(8, $db, 'ALTER TABLE pdo_exec_ddl ADD id INT', 0); + exec_and_count(9, $db, 'ALTER TABLE pdo_exec_ddl ALTER id SET DEFAULT 1', 0); + exec_and_count(10, $db, 'RENAME TABLE pdo_exec_ddl TO pdo_exec_ddl2', 0); + } + + /* + 11.1.2. ALTER LOGFILE GROUP Syntax + 11.1.3. ALTER SERVER Syntax + 11.1.5. ALTER TABLESPACE Syntax + 11.1.8. CREATE LOGFILE GROUP Syntax + 11.1.9. CREATE SERVER Syntax + 11.1.11. CREATE TABLESPACE Syntax + 11.1.14. DROP LOGFILE GROUP Syntax + 11.1.15. DROP SERVER Syntax + 11.1.17. DROP TABLESPACE Syntax + */ + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!";exec('DROP TABLE IF EXISTS pdo_exec_ddl'); +@$db->exec('DROP TABLE IF EXISTS pdo_exec_ddl2'); +@$db->exec('DROP DATABASE IF EXISTS pdo_exec_ddl'); +@$db->exec('DROP DATABASE IF EXISTS pdo_exec_ddl2'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_ddl.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_ddl.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_ddl.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_load_data.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_load_data.php new file mode 100644 index 000000000..aa1c90a37 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_load_data.php @@ -0,0 +1,84 @@ +exec($sql); + if ($ret !== $exp) { + printf("[%03d] Expecting '%s'/%s got '%s'/%s when running '%s', [%s] %s\n", + $offset, $exp, gettype($exp), $ret, gettype($ret), $sql, + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + } catch (PDOException $e) { + + if (42000 == $db->errorCode()) { + // Error: 1148 SQLSTATE: 42000 (ER_NOT_ALLOWED_COMMAND) + // Load data infile not allowed + return false; + } + + printf("[%03d] '%s' has failed, [%s] %s\n", + $offset, $sql, $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return true; + } + + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); + + /* affected rows related */ + try { + + exec_and_count(2, $db, 'DROP TABLE IF EXISTS test', 0); + exec_and_count(3, $db, sprintf('CREATE TABLE test(id INT NOT NULL PRIMARY KEY, col1 CHAR(10)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE), 0); + + $stmt = $db->query("SHOW VARIABLES LIKE 'secure_file_priv'"); + if (($row = $stmt->fetch(PDO::FETCH_ASSOC)) && ($row['value'] != '')) { + $filename = $row['value'] . DIRECTORY_SEPARATOR . "pdo_mysql_exec_load_data.csv"; + } else { + $filename = MySQLPDOTest::getTempDir() . DIRECTORY_SEPARATOR . "pdo_mysql_exec_load_data.csv"; + } + + $fp = fopen($filename, "w"); + fwrite($fp, b"1;foo\n"); + fwrite($fp, b"2;bar"); + fclose($fp); + + $sql = sprintf("LOAD DATA LOCAL INFILE %s INTO TABLE test FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n'", $db->quote($filename)); + + if (exec_and_count(4, $db, $sql, 2)) { + + $stmt = $db->query('SELECT id, col1 FROM test ORDER BY id ASC'); + $expected = array(array("id" => 1, "col1" => "foo"), array("id" => 2, "col1" => "bar")); + $ret = $stmt->fetchAll(PDO::FETCH_ASSOC); + foreach ($expected as $offset => $exp) { + foreach ($exp as $key => $value) { + if ($ret[$offset][$key] != $value) { + printf("Results seem wrong, check manually\n"); + var_dump($ret); + var_dump($expected); + break 2; + } + } + } + } + + unlink($filename); + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_load_data.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_load_data.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_load_data.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_select.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_select.php new file mode 100644 index 000000000..02fed940b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_select.php @@ -0,0 +1,50 @@ +exec($sql); + if ($ret !== $exp) { + printf("[%03d] Expecting '%s'/%s got '%s'/%s when running '%s', [%s] %s\n", + $offset, $exp, gettype($exp), $ret, gettype($ret), $sql, + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + } catch (PDOException $e) { + printf("[%03d] '%s' has failed, [%s] %s\n", + $offset, $sql, $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return true; + } + + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); + + /* affected rows related */ + try { + + exec_and_count(2, $db, 'DROP TABLE IF EXISTS test', 0); + exec_and_count(3, $db, sprintf('CREATE TABLE test(id INT NOT NULL PRIMARY KEY, col1 CHAR(10)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE), 0); + exec_and_count(4, $db, "INSERT INTO test(id, col1) VALUES (1, 'a')", 1); + // question is: will the result set be cleaned up, will it be possible to run more queries on the line? + // buffered or unbuffered does not matter! + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + exec_and_count(5, $db, 'SELECT id FROM test', 0); + exec_and_count(6, $db, "INSERT INTO test(id, col1) VALUES (2, 'b')", 1); + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_select.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_select.php.expectf new file mode 100644 index 000000000..e93f85cfc --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_exec_select.php.expectf @@ -0,0 +1,3 @@ +HipHop Warning: %a +[006] Expecting '1'/integer got ''/boolean when running 'INSERT INTO test(id, col1) VALUES (2, 'b')', [HY000] HY000 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_fetch_both.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_fetch_both.php new file mode 100644 index 000000000..0e2bc43eb --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_fetch_both.php @@ -0,0 +1,50 @@ +query('SELECT 1'); + $num = $stmt->fetch(PDO::FETCH_NUM); + + $stmt = $db->query('SELECT 1'); + $assoc = $stmt->fetch(PDO::FETCH_ASSOC); + + $stmt = $db->query('SELECT 1'); + $both = $stmt->fetch(PDO::FETCH_BOTH); + + $computed_both = array_merge($num, $assoc); + if ($computed_both != $both) { + printf("[%03d] Suspicious FETCH_BOTH result, dumping\n", $offset); + var_dump($computed_both); + var_dump($both); + } + + if (!is_null($expect) && ($expect != $both)) { + printf("[%03d] Expected differes from returned data, dumping\n", $offset); + var_dump($expect); + var_dump($both); + } + + } catch (PDOException $e) { + + printf("[%03d] %s, [%s] %s\n", + $offset, + $e->getMessage(), $db->errroCode(), implode(' ', $db->errorInfo())); + + } + + } + + try { + + fetch(2, $db, 'SELECT 1', array(0 => '1', '1' => '1')); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_fetch_both.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_fetch_both.php.expectf new file mode 100644 index 000000000..fb43721be --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_fetch_both.php.expectf @@ -0,0 +1,27 @@ +[002] Suspicious FETCH_BOTH result, dumping +array(2) { + [0]=> + %unicode|string%(1) "1" + [1]=> + %unicode|string%(1) "1" +} +array(2) { + [1]=> + %unicode|string%(1) "1" + [2]=> + %unicode|string%(1) "1" +} +[002] Expected differes from returned data, dumping +array(2) { + [0]=> + %unicode|string%(1) "1" + [1]=> + %unicode|string%(1) "1" +} +array(2) { + [1]=> + %unicode|string%(1) "1" + [2]=> + %unicode|string%(1) "1" +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_get_attribute.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_get_attribute.php new file mode 100644 index 000000000..08c95d069 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_get_attribute.php @@ -0,0 +1,89 @@ +setAttribute($attribute, $value)) { + printf("[%03d] Cannot set attribute '%s' to value '%s'\n", + $offset, $attribute, var_export($tmp, true)); + return false; + } + + if (gettype($value) != $value_type) { + printf("[%03d] Call to PDO::setAttribute(int attribute, mixed value) has changed the type of value from %s to %s, test will not work properly\n", + $offset, $value_type, gettype($value)); + return false; + } + + $tmp = $db->getAttribute($attribute); + if ($tmp !== $value) { + printf("[%03d] Attribute '%s' was set to '%s'/%s but getAttribute() reports '%s'/%s\n", + $offset, $attribute, var_export($value, true), gettype($value), var_export($tmp, true), gettype($tmp)); + return false; + } + + } catch (PDOException $e) { + printf("[%03d] %s, [%s] %s\n", + $offset, $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return true; + } + + set_and_get(1, $db, PDO::ATTR_AUTOCOMMIT, 1); +/* + set_and_get(2, $db, PDO::ATTR_AUTOCOMMIT, 0); + set_and_get(3, $db, PDO::ATTR_AUTOCOMMIT, -1); + $obj = new stdClass(); + set_and_get(4, $db, PDO::ATTR_AUTOCOMMIT, $obj); + + set_and_get(5, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, 1); + set_and_get(6, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, 0); + set_and_get(7, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, -1); + $tmp = array(); + set_and_get(8, $db, PDO::MYSQL_ATTR_LOCAL_INFILE, $tmp); + + set_and_get(9, $db, PPDO::MYSQL_ATTR_INIT_COMMAND, ''); + set_and_get(10, $db, PPDO::MYSQL_ATTR_INIT_COMMAND, 'SOME SQL'); + set_and_get(11, $db, PPDO::MYSQL_ATTR_INIT_COMMAND, -1); + +*/ +/* +PDO::MYSQL_ATTR_READ_DEFAULT_FILE (integer) + + Read options from the named option file instead of from my.cnf. +PDO::MYSQL_ATTR_READ_DEFAULT_GROUP (integer) + + Read options from the named group from my.cnf or the file specified with MYSQL_READ_DEFAULT_FILE. +PDO::MYSQL_ATTR_MAX_BUFFER_SIZE (integer) + + Maximum buffer size. Defaults to 1 MiB. +PDO::MYSQL_ATTR_DIRECT_QUERY (integer) + + Perform direct queries, don't use prepared statements. +*/ +/* +TODO - read only +PDO::ATTR_CONNECTION_STATUS +PDO::ATTR_SERVER_INFO +*/ + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_get_attribute.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_get_attribute.php.expectf new file mode 100644 index 000000000..6317b258e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_get_attribute.php.expectf @@ -0,0 +1,2 @@ +[001] Call to PDO::setAttribute(int attribute, mixed value) has changed the type of value from integer to boolean, test will not work properly +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_interface.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_interface.php new file mode 100644 index 000000000..ae603c26e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_interface.php @@ -0,0 +1,46 @@ + true, + 'prepare' => true, + 'beginTransaction' => true, + 'commit' => true, + 'rollBack' => true, + 'setAttribute' => true, + 'exec' => true, + 'query' => true, + 'lastInsertId' => true, + 'errorCode' => true, + 'errorInfo' => true, + 'getAttribute' => true, + 'quote' => true, + 'inTransaction' => true, + '__wakeup' => true, + '__sleep' => true, + 'getAvailableDrivers' => true, + ); + $classname = get_class($db); + + $methods = get_class_methods($classname); + foreach ($methods as $k => $method) { + if (isset($expected[$method])) { + unset($expected[$method]); + unset($methods[$k]); + } + if ($method == $classname) { + unset($expected['__construct']); + unset($methods[$k]); + } + } + if (!empty($expected)) { + printf("Dumping missing class methods\n"); + var_dump($expected); + } + if (!empty($methods)) { + printf("Found more methods than expected, dumping list\n"); + var_dump($methods); + } + + print "done!"; \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_interface.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_interface.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_interface.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_last_insert_id.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_last_insert_id.php new file mode 100644 index 000000000..7f9d10a19 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_last_insert_id.php @@ -0,0 +1,105 @@ +lastInsertId())) + printf("[001] No query has been run, lastInsertId() should return '0'/string got '%s'/%s\n", + var_export($tmp, true), gettype($tmp)); + + if ('0' !== ($tmp = $db->lastInsertId('sequence_name'))) + printf("[002] MySQL does not support sequences, expecting '0'/string got '%s'/%s\n", + var_export($tmp, true), gettype($tmp)); + + $db->exec('DROP TABLE IF EXISTS test'); + if ('0' !== ($tmp = $db->lastInsertId())) + printf("[003] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + $db->exec(sprintf('CREATE TABLE test(id INT, col1 CHAR(10)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + if ('0' !== ($tmp = $db->lastInsertId())) + printf("[004] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + $stmt = $db->query('SELECT id FROM test LIMIT 1'); + if ('0' !== ($tmp = $db->lastInsertId())) + printf("[005] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + // no auto increment column + $db->exec("INSERT INTO test(id, col1) VALUES (100, 'a')"); + if ('0' !== ($tmp = $db->lastInsertId())) + printf("[006] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + $db->exec('ALTER TABLE test MODIFY id INT AUTO_INCREMENT PRIMARY KEY'); + if ('0' !== ($tmp = $db->lastInsertId())) + printf("[006] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + // duplicate key + @$db->exec("INSERT INTO test(id, col1) VALUES (100, 'a')"); + if ('0' !== ($tmp = $db->lastInsertId())) + printf("[007] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + $db->exec("INSERT INTO test(id, col1) VALUES (101, 'b')"); + if ('101' !== ($tmp = $db->lastInsertId())) + printf("[008] Expecting '0'/string got '%s'/%s", var_export($tmp, true), gettype($tmp)); + + $db->exec('ALTER TABLE test MODIFY col1 CHAR(10) UNIQUE'); + // replace = delete + insert -> new auto increment value + $db->exec("REPLACE INTO test(col1) VALUES ('b')"); + $next_id = (int)$db->lastInsertId(); + + if ($next_id <= 101) + printf("[009] Expecting at least 102, got %d\n",$next_id); + + $stmt = $db->query('SELECT LAST_INSERT_ID() as _last_id'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $last_id = $row['_last_id']; + if ($next_id != $last_id) { + printf("[010] LAST_INSERT_ID() = %d and lastInserId() = %d differ\n", + $last_id, $next_id); + } + + $db->exec("INSERT INTO test(col1) VALUES ('c'), ('d'), ('e')"); + $next_id = (int)$db->lastInsertId(); + if ($next_id <= $last_id) + printf("[011] Expecting at least %d, got %d\n", $last_id + 1, $next_id); + + // warnings are unhandy, lets go for exceptions for a second + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + try { + $ignore_exception = true; + $db->exec('LOCK TABLE test WRITE'); + $ignore_exception = false; + + if (MySQLPDOTest::getServerVersion($db) >= 50000) { + $stmt = $db->query('SELECT @@auto_increment_increment AS inc'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $inc = $row['inc']; + } else { + $inc = 1; + } + + $stmt = $db->query('SELECT LAST_INSERT_ID() as _last_id'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $last_id = $row['_last_id']; + + $db->exec("INSERT INTO test(col1) VALUES ('z')"); + $next_id = (int)$db->lastInsertId(); + if ($next_id < ($last_id + $inc)) + printf("[012] Expecting at least %d, got %d\n", $last_id + $inc, $next_id); + + } catch (PDOException $e) { + if (!$ignore_exception) + printf("[014] %s, [%s} %s\n", $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); + @$db->exec('UNLOCK TABLE test'); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_last_insert_id.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_last_insert_id.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_last_insert_id.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_pconnect.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_pconnect.php new file mode 100644 index 000000000..55e992c9b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_pconnect.php @@ -0,0 +1,86 @@ + true)); + $db2 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true)); + $db1->exec('SET @pdo_persistent_connection=1'); + $stmt = $db2->query('SELECT @pdo_persistent_connection as _pers'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + if ($tmp['_pers'] !== '1') + printf("[001] Both handles should use the same connection."); + + $stmt = $db1->query('SELECT CONNECTION_ID() as _con1'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $con1 = $tmp['_con1']; + + $stmt = $db2->query('SELECT CONNECTION_ID() as _con2'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $con2 = $tmp['_con2']; + + if ($con1 !== $con2) + printf("[002] Both handles should report the same MySQL thread ID"); + + $db1 = NULL; /* should be equal to closing to my understanding */ + $db1 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true)); + $stmt = $db1->query('SELECT CONNECTION_ID() as _con1'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $con1 = $tmp['_con1']; + + if ($con1 !== $con2) + printf("[003] Both handles should report the same MySQL thread ID"); + + $affected = $db1->exec(sprintf('KILL %d', $con1)); + // Server needs some think-time sometimes + sleep(1); + if ('00000' == $db1->errorCode()) { + // looks like KILL has worked ? Or not... TODO: why no warning with libmysql?! + @$db1->exec("SET @pdo_persistent_connection=2"); + // but now I want to see some error... + if ('HY000' != $db1->errorCode()) + printf("[004] Wrong error code %s\n", $db1->errorCode()); + + $tmp = implode(' ', $db1->errorInfo()); + if (!strstr($tmp, '2006')) + printf("[005] Wrong error info %s\n", $tmp); + } + + $db1 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => false)); + $stmt = $db1->query('SELECT CONNECTION_ID() as _con1'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $con1 = $tmp['_con1']; + + $db2 = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true)); + $stmt = $db2->query('SELECT CONNECTION_ID() as _con2'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + $con2 = $tmp['_con2']; + + if ($con1 == $con2) + printf("[006] Looks like the persistent and the non persistent connection are using the same link?!\n"); + + // lets go crazy and create a few pconnections... + $connections = array(); + for ($i = 0; $i <= 20; $i++) { + $connections[$i] = new PDO($dsn, $user, $pass, array(PDO::ATTR_PERSISTENT => true)); + } + do { + $i = mt_rand(0, 20); + if (isset($connections[$i])) + unset($connections[$i]); + } while (!empty($connections)); + + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s\n", + $e->getMessage(), + (is_object($db)) ? $db->errorCode() : 'n/a', + (is_object($db)) ? implode(' ', $db->errorInfo()) : 'n/a'); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_pconnect.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_pconnect.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_pconnect.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_phpinfo.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_phpinfo.php new file mode 100644 index 000000000..866a7e521 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_phpinfo.php @@ -0,0 +1,19 @@ + 6.0.3-alpha */ + $expected = sprintf('Client API version => %s', + $db->getAttribute(PDO::ATTR_CLIENT_VERSION)); + + if (false === stristr($tmp, $expected)) { + printf("[001] Cannot find MySQL PDO driver line in phpinfo() output\n"); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_phpinfo.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_phpinfo.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_phpinfo.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated.php new file mode 100644 index 000000000..3f7171e7f --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated.php @@ -0,0 +1,314 @@ +prepare($query); + else + $stmt = $db->prepare($query); + + if (is_array($error_info) && isset($error_info['prepare'])) { + $tmp = $db->errorInfo(); + + if (isset($error_info['prepare']['sqlstate']) && + ($error_info['prepare']['sqlstate'] !== $tmp[0])) { + printf("[%03d] prepare() - expecting SQLSTATE '%s' got '%s'\n", + $offset, $error_info['prepare']['sqlstate'], $tmp[0]); + return false; + } + + if (isset($error_info['prepare']['mysql']) && + ($error_info['prepare']['mysql'] !== $tmp[1])) { + printf("[%03d] prepare() - expecting MySQL Code '%s' got '%s'\n", + $offset, $error_info['prepare']['mysql'], $tmp[0]); + return false; + } + + return false; + } + + if (is_null($input_params)) + $input_params = array(); + + if (is_array($error_info) && isset($error_info['execute'])) + $ret = @$stmt->execute($input_params); + else + $ret = $stmt->execute($input_params); + + if (!is_bool($ret)) + printf("[%03d] PDO::execute() should return a boolean value, got %s/%s\n", + var_export($ret, true), $ret); + + if (is_array($error_info) && isset($error_info['execute'])) { + $tmp = $stmt->errorInfo(); + + if (isset($error_info['execute']['sqlstate']) && + ($error_info['execute']['sqlstate'] !== $tmp[0])) { + printf("[%03d] execute() - expecting SQLSTATE '%s' got '%s'\n", + $offset, $error_info['execute']['sqlstate'], $tmp[0]); + return false; + } + + if (isset($error_info['execute']['mysql']) && + ($error_info['execute']['mysql'] !== $tmp[1])) { + printf("[%03d] execute() - expecting MySQL Code '%s' got '%s'\n", + $offset, $error_info['execute']['mysql'], $tmp[0]); + return false; + } + + return false; + } + + } catch (PDOException $e) { + printf("[%03d] %s, [%s} %s\n", + $offset, $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return $stmt; + } + + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); + + // TODO - that's PDO - you can prepare empty statements! + prepex(3, $db, '', + array(), array('execute' => array('sqlstate' => '42000'))); + + // lets be fair and do the most simple SELECT first + $stmt = prepex(4, $db, 'SELECT 1 as "one"'); + var_dump($stmt->fetch(PDO::FETCH_ASSOC)); + + prepex(5, $db, 'DROP TABLE IF EXISTS test'); + prepex(6, $db, sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + prepex(7, $db, "INSERT INTO test(id, label) VALUES(1, ':placeholder')"); + $stmt = prepex(8, $db, 'SELECT label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + prepex(9, $db, 'DELETE FROM test'); + prepex(10, $db, "INSERT INTO test(id, label) VALUES(1, ':placeholder')", + array(':placeholder' => 'first row')); + $stmt = prepex(11, $db, 'SELECT label FROM test'); + + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + prepex(12, $db, 'DELETE FROM test'); + prepex(13, $db, 'INSERT INTO test(id, label) VALUES(1, :placeholder)', + array(':placeholder' => 'first row')); + prepex(14, $db, 'INSERT INTO test(id, label) VALUES(2, :placeholder)', + array(':placeholder' => 'second row')); + $stmt = prepex(15, $db, 'SELECT label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Is PDO fun? + prepex(16, $db, 'SELECT label FROM test WHERE :placeholder > 1', + array(':placeholder' => 'id')); + prepex(17, $db, 'SELECT :placeholder FROM test WHERE id > 1', + array(':placeholder' => 'id')); + prepex(18, $db, 'SELECT :placeholder FROM test WHERE :placeholder > :placeholder', + array(':placeholder' => 'test')); + + for ($num_params = 2; $num_params < 100; $num_params++) { + $params = array(':placeholder' => 'a'); + for ($i = 1; $i < $num_params; $i++) { + $params[str_repeat('a', $i)] = 'some data'; + } + prepex(19, $db, 'SELECT id, label FROM test WHERE label > :placeholder', + $params, array('execute' => array('sqlstate' => 'HY093'))); + } + + prepex(20, $db, 'DELETE FROM test'); + prepex(21, $db, 'INSERT INTO test(id, label) VALUES (1, :placeholder), (2, :placeholder)', + array(':placeholder' => 'row')); + $stmt = prepex(22, $db, 'SELECT id, label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = prepex(23, $db, 'SELECT id, label FROM test WHERE :placeholder IS NOT NULL', + array(':placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[024] '1' IS NOT NULL evaluates to true, expecting two rows, got %d rows\n", $tmp); + + $stmt = prepex(25, $db, 'SELECT id, label FROM test WHERE :placeholder IS NULL', + array(':placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[026] '1' IS NOT NULL evaluates to true, expecting zero rows, got %d rows\n", $tmp); + + prepex(27, $db, 'DROP TABLE IF EXISTS test'); + prepex(28, $db, 'CREATE TABLE test(id INT, label CHAR(255)) ENGINE=MyISAM'); + if (is_object(prepex(29, $db, 'CREATE FULLTEXT INDEX idx1 ON test(label)'))) { + prepex(30, $db, 'INSERT INTO test(id, label) VALUES (1, :placeholder)', + array(':placeholder' => 'MySQL is the best database in the world!')); + prepex(31, $db, 'INSERT INTO test(id, label) VALUES (1, :placeholder)', + array(':placeholder' => 'If I have the freedom to choose, I would always go again for the MySQL Server')); + $stmt = prepex(32, $db, 'SELECT id, label FROM test WHERE MATCH label AGAINST (:placeholder)', + array(':placeholder' => 'mysql')); + /* + Lets ignore this + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[033] Expecting two rows, got %d rows\n", $tmp); + */ + } + prepex(34, $db, 'DELETE FROM test'); + prepex(35, $db, 'INSERT INTO test(id, label) VALUES (1, :placeholder), (2, :placeholder)', + array(':placeholder' => 'row')); +/* + $stmt = prepex(36, $db, 'SELECT id, label FROM "test WHERE MATCH label AGAINST (:placeholder)', + array(':placeholder' => 'row'), + array('execute' => array('sqlstate' => '42000', 'mysql' => 1064))); +*/ + $stmt = prepex(37, $db, 'SELECT id, label FROM \'test WHERE MATCH label AGAINST (:placeholder)', + array(':placeholder' => 'row'), + array('execute' => array('sqlstate' => '42000', 'mysql' => 1064))); + + $stmt = prepex(38, $db, 'SELECT id, label AS "label" FROM test WHERE label = :placeholder', + array(':placeholder' => 'row')); + + $sql = sprintf("SELECT id, label FROM test WHERE (label LIKE %s) AND (id = :placeholder)", + $db->quote('%ro%')); + $stmt = prepex(39, $db, $sql, array('placeholder' => -1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[040] Expecting zero rows, got %d rows\n", $tmp); + + + $sql = sprintf("SELECT id, label FROM test WHERE (id = :placeholder) OR (label LIKE %s)", + $db->quote('%ro%')); + $stmt = prepex(41, $db, $sql, array('placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[042] Expecting two rows, got %d rows\n", $tmp); + + $sql = "SELECT id, label FROM test WHERE id = :placeholder AND label = (SELECT label AS 'SELECT' FROM test WHERE id = :placeholder)"; + $stmt = prepex(43, $db, $sql, array('placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 1) + printf("[044] Expecting onw row, got %d rows\n", $tmp); + + // and now, the same with anonymous placeholders... + prepex(45, $db, 'DROP TABLE IF EXISTS test'); + prepex(46, $db, sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + prepex(47, $db, "INSERT INTO test(id, label) VALUES(1, '?')"); + $stmt = prepex(48, $db, 'SELECT label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + prepex(49, $db, 'DELETE FROM test'); + prepex(50, $db, "INSERT INTO test(id, label) VALUES(1, '?')", + array('first row')); + $stmt = prepex(51, $db, 'SELECT label FROM test'); + + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + prepex(52, $db, 'DELETE FROM test'); + prepex(53, $db, 'INSERT INTO test(id, label) VALUES(1, ?)', + array('first row')); + prepex(54, $db, 'INSERT INTO test(id, label) VALUES(2, ?)', + array('second row')); + $stmt = prepex(55, $db, 'SELECT label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Is PDO fun? + prepex(56, $db, 'SELECT label FROM test WHERE ? > 1', + array('id')); + prepex(57, $db, 'SELECT ? FROM test WHERE id > 1', + array('id')); + prepex(58, $db, 'SELECT ? FROM test WHERE ? > ?', + array('test'), array('execute' => array('sqlstate' => 'HY093'))); + + prepex(59, $db, 'SELECT ? FROM test WHERE ? > ?', + array('id', 'label', 'value')); + + for ($num_params = 2; $num_params < 100; $num_params++) { + $params = array('a'); + for ($i = 1; $i < $num_params; $i++) { + $params[] = 'some data'; + } + prepex(60, $db, 'SELECT id, label FROM test WHERE label > ?', + $params, array('execute' => array('sqlstate' => 'HY093'))); + } + + prepex(61, $db, 'DELETE FROM test'); + prepex(62, $db, 'INSERT INTO test(id, label) VALUES (1, ?), (2, ?)', + array('row', 'row')); + $stmt = prepex(63, $db, 'SELECT id, label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = prepex(64, $db, 'SELECT id, label FROM test WHERE ? IS NOT NULL', + array(1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[065] '1' IS NOT NULL evaluates to true, expecting two rows, got %d rows\n", $tmp); + + $stmt = prepex(66, $db, 'SELECT id, label FROM test WHERE ? IS NULL', + array(1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[067] '1' IS NOT NULL evaluates to true, expecting zero rows, got %d rows\n", $tmp); + + prepex(68, $db, 'DROP TABLE IF EXISTS test'); + prepex(69, $db, 'CREATE TABLE test(id INT, label CHAR(255)) ENGINE=MyISAM'); + if (is_object(prepex(70, $db, 'CREATE FULLTEXT INDEX idx1 ON test(label)'))) { + prepex(71, $db, 'INSERT INTO test(id, label) VALUES (1, ?)', + array('MySQL is the best database in the world!')); + prepex(72, $db, 'INSERT INTO test(id, label) VALUES (1, ?)', + array('If I have the freedom to choose, I would always go again for the MySQL Server')); + $stmt = prepex(73, $db, 'SELECT id, label FROM test WHERE MATCH label AGAINST (?)', + array('mysql')); + /* + Lets ignore that + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[074] Expecting two rows, got %d rows\n", $tmp); + */ + } + + prepex(74, $db, 'DELETE FROM test'); + prepex(75, $db, 'INSERT INTO test(id, label) VALUES (1, ?), (2, ?)', + array('row', 'row')); + + $stmt = prepex(76, $db, 'SELECT id, label FROM "test WHERE MATCH label AGAINST (?)', + array('row'), + array('execute' => array('sqlstate' => '42000', 'mysql' => 1064))); + + /* + TODO enable after fix + $stmt = prepex(37, $db, 'SELECT id, label FROM \'test WHERE MATCH label AGAINST (:placeholder)', + array(':placeholder' => 'row'), + array('execute' => array('sqlstate' => '42000', 'mysql' => 1064))); + */ + + $stmt = prepex(78, $db, 'SELECT id, label AS "label" FROM test WHERE label = ?', + array('row')); + + $sql = sprintf("SELECT id, label FROM test WHERE (label LIKE %s) AND (id = ?)", + $db->quote('%ro%')); + $stmt = prepex(79, $db, $sql, array(-1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[080] Expecting zero rows, got %d rows\n", $tmp); + + + $sql = sprintf("SELECT id, label FROM test WHERE (id = ?) OR (label LIKE %s)", + $db->quote('%ro%')); + $stmt = prepex(81, $db, $sql, array(1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[082] Expecting two rows, got %d rows\n", $tmp); + + $sql = "SELECT id, label FROM test WHERE id = ? AND label = (SELECT label AS 'SELECT' FROM test WHERE id = ?)"; + $stmt = prepex(83, $db, $sql, array(1, 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 1) + printf("[084] Expecting one row, got %d rows\n", $tmp); + + $sql = "SELECT id, label FROM test WHERE id = :placeholder AND label = (SELECT label AS 'SELECT' FROM test WHERE id = ?)"; + $stmt = prepex(85, $db, $sql, array(1, 1), array('execute' => array('sqlstate' => 'HY093'))); + if (is_object($stmt) && count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[086] Expecting no rows, got %d rows\n", $tmp); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated.php.expectf new file mode 100644 index 000000000..504ac255c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated.php.expectf @@ -0,0 +1,89 @@ +array(1) { + [%u|b%"one"]=> + %unicode|string%(1) "1" +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(12) ":placeholder" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(12) ":placeholder" + } +} +array(2) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(9) "first row" + } + [1]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(10) "second row" + } +} +array(2) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(3) "row" + } + [1]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(3) "row" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(1) "?" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(1) "?" + } +} +array(2) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(9) "first row" + } + [1]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(10) "second row" + } +} +array(2) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(3) "row" + } + [1]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(3) "row" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_anonymous.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_anonymous.php new file mode 100644 index 000000000..e02550052 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_anonymous.php @@ -0,0 +1,54 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to switch to emulated prepared statements, test will fail\n"); + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + + $stmt = $db->prepare("INSERT INTO test(id, label) VALUES(1, '?')"); + // you can bind as many values as you want no matter if they can be replaced or not + $stmt->execute(array('first row')); + if ('00000' !== $stmt->errorCode()) + printf("[003] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + $stmt = $db->prepare('SELECT id, label FROM test'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // now the same with native PS + printf("now the same with native PS\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to switch off emulated prepared statements, test will fail\n"); + + $db->exec('DELETE FROM test'); + $stmt = $db->prepare("INSERT INTO test(id, label) VALUES(1, '?')"); + // you can bind as many values as you want no matter if they can be replaced or not + $stmt->execute(array('first row')); + if ('00000' !== $stmt->errorCode()) + printf("[005] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + $stmt = $db->prepare('SELECT id, label FROM test'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_anonymous.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_anonymous.php.expectf new file mode 100644 index 000000000..4b26f6eb6 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_anonymous.php.expectf @@ -0,0 +1,18 @@ +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "?" + } +} +now the same with native PS +[005] Execute has failed, 'HY093' array ( + 0 => 'HY093', + 1 => NULL, + 2 => NULL, +) +array(0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_placeholder_everywhere.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_placeholder_everywhere.php new file mode 100644 index 000000000..d84539bb1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_placeholder_everywhere.php @@ -0,0 +1,50 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to switch off emulated prepared statements, test will fail\n"); + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + $db->exec("INSERT INTO test(id, label) VALUES (1, 'row1')"); + + // So, what will happen? More placeholder but values and + // placeholders in interesting places... + $stmt = $db->prepare('SELECT ? FROM test WHERE ? > ?'); + $stmt->execute(array('test')); + if ('00000' !== $stmt->errorCode()) { + printf("[003] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + } + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // now the same with emulated PS + printf("now the same with emulated PS\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to switch on emulated prepared statements, test will fail\n"); + + $stmt = $db->prepare('SELECT ? FROM test WHERE ? > ?'); + $stmt->execute(array('test')); + if ('00000' !== $stmt->errorCode()) + printf("[005] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_placeholder_everywhere.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_placeholder_everywhere.php.expectf new file mode 100644 index 000000000..ba14d5d80 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_emulated_placeholder_everywhere.php.expectf @@ -0,0 +1,19 @@ +HipHop Warning: %a +[003] Execute has failed, 'HY093' array ( + 0 => 'HY093', + 1 => NULL, + 2 => NULL, +) +array(0) { +} +now the same with emulated PS +HipHop Warning: %a +HipHop Warning: %a +[005] Execute has failed, 'HY093' array ( + 0 => 'HY093', + 1 => NULL, + 2 => NULL, +) +array(0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_load_data.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_load_data.php new file mode 100644 index 000000000..6e08fa867 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_load_data.php @@ -0,0 +1,88 @@ +exec($sql); + if ($ret !== $exp) { + printf("[%03d] Expecting '%s'/%s got '%s'/%s when running '%s', [%s] %s\n", + $offset, $exp, gettype($exp), $ret, gettype($ret), $sql, + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + } catch (PDOException $e) { + + if (42000 == $db->errorCode()) { + // Error: 1148 SQLSTATE: 42000 (ER_NOT_ALLOWED_COMMAND) + // Load data infile not allowed + return false; + } + + printf("[%03d] '%s' has failed, [%s] %s\n", + $offset, $sql, $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return true; + } + + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + $db = MySQLPDOTest::factory(); + // Run with native PS. + // The test is about checking the fallback to emulation + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + MySQLPDOTest::createTestTable($db, MySQLPDOTest::detect_transactional_mysql_engine($db)); + + /* affected rows related */ + try { + + exec_and_count(2, $db, 'DROP TABLE IF EXISTS test', 0); + exec_and_count(3, $db, sprintf('CREATE TABLE test(id INT NOT NULL PRIMARY KEY, col1 CHAR(10)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE), 0); + + $stmt = $db->query("SHOW VARIABLES LIKE 'secure_file_priv'"); + if (($row = $stmt->fetch(PDO::FETCH_ASSOC)) && ($row['value'] != '')) { + $filename = $row['value'] . DIRECTORY_SEPARATOR . "pdo_mysql_exec_load_data.csv"; + } else { + $filename = MySQLPDOTest::getTempDir() . DIRECTORY_SEPARATOR . "pdo_mysql_exec_load_data.csv"; + } + + $fp = fopen($filename, "w"); + fwrite($fp, b"1;foo\n"); + fwrite($fp, b"2;bar"); + fclose($fp); + + // This should fail, the PS protocol should not support it. + // mysqlnd will give 2014 as a follow-up of the fallback logic + // libmysql will give a little more precise 2030 error code + // However, you get an error and the big question is what happens to the line + $stmt = $db->prepare(sprintf("LOAD DATA INFILE %s INTO TABLE test FIELDS TERMINATED BY ';' LINES TERMINATED BY '\n'", $db->quote($filename))); + if (!$stmt->execute()) { + printf("[004] [%d] %s\n", $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + } + + // Check the line + $stmt = $db->query("SELECT 1 as 'one'"); + if ($stmt->errorCode() != '0000') { + printf("[005] [%d] %s\n", $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + } else { + $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (!isset($rows[0]['one']) || $rows[0]['one'] != 1) + printf("[006] [%d] %s\n", $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + } + + unlink($filename); + + } catch (PDOException $e) { + printf("[001] %s, [%s] %s (%s)\n", + $e->getMessage(), + $db->errorCode(), + implode(' ', $db->errorInfo()), + (isset($stmt)) ? implode(' ', $stmt->errorInfo()) : 'N/A'); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_load_data.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_load_data.php.expectf new file mode 100644 index 000000000..3913104a6 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_load_data.php.expectf @@ -0,0 +1,7 @@ +HipHop Warning: %a +[004] [0] array ( + 0 => 'HY000', + 1 => %d, + 2 => %s, +) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_match_against.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_match_against.php new file mode 100644 index 000000000..f498efd75 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_match_against.php @@ -0,0 +1,35 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=MyISAM'); + $db->exec('CREATE FULLTEXT INDEX idx1 ON test(label)'); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE MATCH label AGAINST (:placeholder)'); + $stmt->execute(array(':placeholder' => 'row')); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE MATCH label AGAINST (:placeholder)'); + $stmt->execute(array('placeholder' => 'row')); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE MATCH label AGAINST (?)'); + $stmt->execute(array('row')); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } catch (PDOException $e) { + + printf("[001] %s, [%s} %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_match_against.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_match_against.php.expectf new file mode 100644 index 000000000..b348d979d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_match_against.php.expectf @@ -0,0 +1,7 @@ +array(0) { +} +array(0) { +} +array(0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native.php new file mode 100644 index 000000000..175a1d4c9 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native.php @@ -0,0 +1,331 @@ +prepare($query); + else + $stmt = $db->prepare($query); + + if (is_array($error_info) && isset($error_info['prepare'])) { + $tmp = $db->errorInfo(); + + if (isset($error_info['prepare']['sqlstate']) && + ($error_info['prepare']['sqlstate'] !== $tmp[0])) { + printf("[%03d] prepare() - expecting SQLSTATE '%s' got '%s'\n", + $offset, $error_info['prepare']['sqlstate'], $tmp[0]); + return false; + } + + if (isset($error_info['prepare']['mysql']) && + ($error_info['prepare']['mysql'] !== $tmp[1])) { + printf("[%03d] prepare() - expecting MySQL Code '%s' got '%s'\n", + $offset, $error_info['prepare']['mysql'], $tmp[0]); + return false; + } + + return false; + } + + if (!is_object($stmt)) + return false; + + if (is_null($input_params)) + $input_params = array(); +// 5.0.18, 5.1.14 @ 15 +// printf("[%03d]\n", $offset); + if ($suppress_warning || (is_array($error_info) && isset($error_info['execute']))) + $ret = @$stmt->execute($input_params); + else + $ret = $stmt->execute($input_params); + + if (!is_bool($ret)) + printf("[%03d] PDO::execute() should return a boolean value, got %s/%s\n", + var_export($ret, true), $ret); + + $tmp = $stmt->errorInfo(); + if (isset($tmp[1]) && ($tmp[1] == 2030)) { + // Trying to hack around MySQL Server version dependent features + // 2030 This command is not supported in the prepared statement protocol yet + return false; + } + + if (is_array($error_info) && isset($error_info['execute'])) { + + if (isset($error_info['execute']['sqlstate']) && + ($error_info['execute']['sqlstate'] !== $tmp[0])) { + printf("[%03d] execute() - expecting SQLSTATE '%s' got '%s'\n", + $offset, $error_info['execute']['sqlstate'], $tmp[0]); + return false; + } + + if (isset($error_info['execute']['mysql']) && + ($error_info['execute']['mysql'] !== $tmp[1])) { + printf("[%03d] execute() - expecting MySQL Code '%s' got '%s'\n", + $offset, $error_info['execute']['mysql'], $tmp[0]); + return false; + } + + return false; + + } + + } catch (PDOException $e) { + printf("[%03d] %s, [%s} %s\n", + $offset, $e->getMessage(), + $db->errorCode(), implode(' ', $db->errorInfo())); + return false; + } + + return $stmt; + } + + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + // TODO - that's PDO - you can prepare empty statements! + prepex(3, $db, '', + array(), array('prepare' => array('sqlstate' => '42000'))); + + // lets be fair and do the most simple SELECT first + $stmt = prepex(4, $db, 'SELECT 1 as "one"'); + if (MySQLPDOTest::isPDOMySQLnd()) + // native types - int + $expected = array('one' => 1); + else + // always strings, like STRINGIFY flag + $expected = array('one' => '1'); + + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if ($row !== $expected) { + printf("[004a] Expecting %s got %s\n", var_export($expected, true), var_export($row, true)); + } + + prepex(5, $db, 'DROP TABLE IF EXISTS test'); + prepex(6, $db, sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + prepex(7, $db, "INSERT INTO test(id, label) VALUES(1, ':placeholder')"); + $stmt = prepex(8, $db, 'SELECT label FROM test ORDER BY id ASC'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + prepex(9, $db, 'DELETE FROM test'); + prepex(10, $db, 'INSERT INTO test(id, label) VALUES(1, :placeholder)', + array(':placeholder' => 'first row')); + prepex(11, $db, 'INSERT INTO test(id, label) VALUES(2, :placeholder)', + array(':placeholder' => 'second row')); + $stmt = prepex(12, $db, 'SELECT label FROM test ORDER BY id ASC'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Is PDO fun? + $stmt = prepex(13, $db, 'SELECT label FROM test WHERE :placeholder > 1', + array(':placeholder' => 'id')); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + for ($num_params = 2; $num_params < 100; $num_params++) { + $params = array(':placeholder' => 'a'); + for ($i = 1; $i < $num_params; $i++) { + $params[str_repeat('a', $i)] = 'some data'; + } + prepex(16, $db, 'SELECT id, label FROM test WHERE label > :placeholder', + $params, array('execute' => array('sqlstate' => 'HY093'))); + } + + $stmt = prepex(16, $db, 'SELECT id, label FROM test WHERE :placeholder IS NOT NULL', + array(':placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[017] '1' IS NOT NULL evaluates to true, expecting two rows, got %d rows\n", $tmp); + + $stmt = prepex(18, $db, 'SELECT id, label FROM test WHERE :placeholder IS NULL', + array(':placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[019] '1' IS NOT NULL evaluates to true, expecting zero rows, got %d rows\n", $tmp); + + prepex(20, $db, 'DROP TABLE IF EXISTS test'); + prepex(21, $db, 'CREATE TABLE test(id INT, label CHAR(255)) ENGINE=MyISAM'); + // Not every MySQL Server version supports this + if (is_object(prepex(22, $db, 'CREATE FULLTEXT INDEX idx1 ON test(label)', null, null, true))) { + prepex(23, $db, 'INSERT INTO test(id, label) VALUES (1, :placeholder)', + array(':placeholder' => 'MySQL is the best database in the world!')); + prepex(24, $db, 'INSERT INTO test(id, label) VALUES (2, :placeholder)', + array(':placeholder' => 'If I have the freedom to choose, I would always go again for the MySQL Server')); + $stmt = prepex(25, $db, 'SELECT id, label FROM test WHERE MATCH label AGAINST (:placeholder)', + array(':placeholder' => 'mysql'), null, true); + if (is_object($stmt)) { + /* + Lets ignore this + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[033] Expecting two rows, got %d rows\n", $tmp); + */ + $stmt = prepex(26, $db, 'SELECT id, label FROM test ORDER BY id ASC'); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[027] Expecting two rows, got %d rows\n", $tmp); + + if ($tmp[0]['label'] !== 'MySQL is the best database in the world!') { + printf("[028] INSERT seems to have failed, dumping data, check manually\n"); + var_dump($tmp); + } + } + } + + $db->exec('DELETE FROM test'); + $db->exec("INSERT INTO test(id, label) VALUES (1, 'row1')"); + $db->exec("INSERT INTO test(id, label) VALUES (2, 'row2')"); + + $sql = sprintf("SELECT id, label FROM test WHERE (label LIKE %s) AND (id = :placeholder)", + $db->quote('%ro%')); + $stmt = prepex(29, $db, $sql, array('placeholder' => -1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[030] Expecting zero rows, got %d rows\n", $tmp); + + $sql = sprintf("SELECT id, label FROM test WHERE (id = :placeholder) OR (label LIKE %s)", + $db->quote('%go%')); + $stmt = prepex(31, $db, $sql, array('placeholder' => 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 1) + printf("[032] Expecting one row, got %d rows\n", $tmp); + + // and now, the same with anonymous placeholders... + prepex(33, $db, 'DROP TABLE IF EXISTS test'); + prepex(34, $db, sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + prepex(35, $db, "INSERT INTO test(id, label) VALUES(1, '?')"); + $stmt = prepex(36, $db, 'SELECT label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + prepex(37, $db, 'DELETE FROM test'); + prepex(38, $db, 'INSERT INTO test(id, label) VALUES(1, ?)', + array('first row')); + prepex(39, $db, 'INSERT INTO test(id, label) VALUES(2, ?)', + array('second row')); + $stmt = prepex(40, $db, 'SELECT label FROM test'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Is PDO fun? + prepex(40, $db, 'SELECT label FROM test WHERE ? > 1', + array('id')); + prepex(41, $db, 'SELECT ? FROM test WHERE id > 1', + array('id')); + prepex(42, $db, 'SELECT ? FROM test WHERE ? > ?', + array('id', 'label', 'value')); + + for ($num_params = 2; $num_params < 100; $num_params++) { + $params = array('a'); + for ($i = 1; $i < $num_params; $i++) { + $params[] = 'some data'; + } + prepex(43, $db, 'SELECT id, label FROM test WHERE label > ?', + $params, array('execute' => array('sqlstate' => 'HY093'))); + } + + prepex(44, $db, 'DELETE FROM test'); + prepex(45, $db, 'INSERT INTO test(id, label) VALUES (1, ?), (2, ?)', + array('row', 'row')); + $stmt = prepex(46, $db, 'SELECT id, label FROM test'); + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + $exp = array( + 0 => array( + "id" => "1", + "label" => "row" + ), + 1 => array( + "id" => "2", + "label" => "row" + ), + ); + + if (MySQLPDOTest::isPDOMySQLnd()) { + // mysqlnd returns native types + $exp[0]['id'] = 1; + $exp[1]['id'] = 2; + } + if ($tmp !== $exp) { + printf("[064] Results seem wrong. Please check dumps manually.\n"); + var_dump($exp); + var_dump($tmp); + } + + $stmt = prepex(47, $db, 'SELECT id, label FROM test WHERE ? IS NOT NULL', + array(1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[048] '1' IS NOT NULL evaluates to true, expecting two rows, got %d rows\n", $tmp); + + $stmt = prepex(49, $db, 'SELECT id, label FROM test WHERE ? IS NULL', + array(1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[050] '1' IS NOT NULL evaluates to true, expecting zero rows, got %d rows\n", $tmp); + + prepex(51, $db, 'DROP TABLE IF EXISTS test'); + prepex(52, $db, 'CREATE TABLE test(id INT, label CHAR(255)) ENGINE=MyISAM'); + if (is_object(prepex(53, $db, 'CREATE FULLTEXT INDEX idx1 ON test(label)', null, null, true))) { + prepex(54, $db, 'INSERT INTO test(id, label) VALUES (1, ?)', + array('MySQL is the best database in the world!')); + prepex(55, $db, 'INSERT INTO test(id, label) VALUES (1, ?)', + array('If I have the freedom to choose, I would always go again for the MySQL Server')); + $stmt = prepex(56, $db, 'SELECT id, label FROM test WHERE MATCH label AGAINST (?)', + array('mysql'), null, true); + /* + Lets ignore that + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[074] Expecting two rows, got %d rows\n", $tmp); + */ + } + + prepex(57, $db, 'DELETE FROM test'); + prepex(58, $db, 'INSERT INTO test(id, label) VALUES (1, ?), (2, ?)', + array('row1', 'row2')); + + /* + TODO enable after fix + $stmt = prepex(37, $db, 'SELECT id, label FROM \'test WHERE MATCH label AGAINST (:placeholder)', + array(':placeholder' => 'row'), + array('execute' => array('sqlstate' => '42000', 'mysql' => 1064))); + */ + + $stmt = prepex(59, $db, 'SELECT id, label AS "label" FROM test WHERE label = ?', + array('row1')); + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + $exp = array( + 0 => array("id" => "1", "label" => "row1") + ); + + if (MySQLPDOTest::isPDOMySQLnd()) { + // mysqlnd returns native types + $exp[0]['id'] = 1; + } + if ($tmp !== $exp) { + printf("[065] Results seem wrong. Please check dumps manually.\n"); + var_dump($exp); + var_dump($tmp); + } + + $sql = sprintf("SELECT id, label FROM test WHERE (label LIKE %s) AND (id = ?)", + $db->quote('%ro%')); + $stmt = prepex(60, $db, $sql, array(-1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 0) + printf("[061] Expecting zero rows, got %d rows\n", $tmp); + + $sql = sprintf("SELECT id, label FROM test WHERE (id = ?) OR (label LIKE %s)", + $db->quote('%ro%')); + $stmt = prepex(61, $db, $sql, array(1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 2) + printf("[062] Expecting two rows, got %d rows\n", $tmp); + + $sql = "SELECT id, label FROM test WHERE id = ? AND label = (SELECT label AS 'SELECT' FROM test WHERE id = ?)"; + $stmt = prepex(63, $db, $sql, array(1, 1)); + if (count(($tmp = $stmt->fetchAll(PDO::FETCH_ASSOC))) != 1) + printf("[064] Expecting one row, got %d rows\n", $tmp); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native.php.expectf new file mode 100644 index 000000000..ecc0ef786 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native.php.expectf @@ -0,0 +1,41 @@ +array(1) { + [0]=> + array(1) { + ["label"]=> + string(12) ":placeholder" + } +} +array(2) { + [0]=> + array(1) { + ["label"]=> + string(9) "first row" + } + [1]=> + array(1) { + ["label"]=> + string(10) "second row" + } +} +array(0) { +} +array(1) { + [0]=> + array(1) { + ["label"]=> + string(1) "?" + } +} +array(2) { + [0]=> + array(1) { + ["label"]=> + string(9) "first row" + } + [1]=> + array(1) { + ["label"]=> + string(10) "second row" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_clear_error.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_clear_error.php new file mode 100644 index 000000000..5c80eab87 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_clear_error.php @@ -0,0 +1,64 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + + // We need to run the emulated version first. Native version will cause a fatal error + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + // INSERT a single row + $db->exec("INSERT INTO test(id, label) VALUES (1, 'row1')"); + + $stmt = $db->prepare('SELECT unknown_column FROM test WHERE id > :placeholder ORDER BY id ASC'); + $stmt->execute(array(':placeholder' => 0)); + if ('00000' !== $stmt->errorCode()) + printf("[003] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > :placeholder ORDER BY id ASC'); + $stmt->execute(array(':placeholder' => 0)); + if ('00000' !== $stmt->errorCode()) + printf("[004] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Native PS + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[005] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT unknown_column FROM test WHERE id > :placeholder ORDER BY id ASC'); + $stmt->execute(array(':placeholder' => 0)); + if ('00000' !== $stmt->errorCode()) + printf("[006] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > :placeholder ORDER BY id ASC'); + $stmt->execute(array(':placeholder' => 0)); + if ('00000' !== $stmt->errorCode()) + printf("[007] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_clear_error.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_clear_error.php.expectf new file mode 100644 index 000000000..3f3c3a2e2 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_clear_error.php.expectf @@ -0,0 +1,17 @@ +HipHop Warning: %a +[003] Execute has failed, '42S22' array ( + 0 => '42S22', + 1 => 1054, + 2 => 'Unknown column \'unknown_column\' in \'field list\'', +) +array(1) { + [0]=> + array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(4) "row1" + } +} +HipHop Warning: %a +HipHop Fatal error: %a \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_column.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_column.php new file mode 100644 index 000000000..01832e70d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_column.php @@ -0,0 +1,24 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare("SELECT :param FROM test ORDER BY id ASC LIMIT 1"); + $stmt->execute(array(':param' => 'id')); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $db->prepare('SELECT :placeholder FROM test WHERE :placeholder > :placeholder'); + $stmt->execute(array(':placeholder' => 'test')); + + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_column.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_column.php.expectf new file mode 100644 index 000000000..7848e6536 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_column.php.expectf @@ -0,0 +1,11 @@ +array(1) { + [0]=> + array(1) { + ["?"]=> + string(2) "id" + } +} +HipHop Warning: %a +array(0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_dup_named_placeholder.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_dup_named_placeholder.php new file mode 100644 index 000000000..62b3bfae2 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_dup_named_placeholder.php @@ -0,0 +1,90 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label1 CHAR(255), label2 CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + printf("Native...\n"); + + // INSERT a single row + $stmt = $db->prepare('INSERT INTO test(id, label1, label2) VALUES (1, :placeholder, :placeholder)'); + + $stmt->execute(array(':placeholder' => 'row1')); + if ('00000' !== $stmt->errorCode()) + printf("[003] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + // Ok, what has happened: anything inserted into the DB? + $stmt = $db->prepare('SELECT id, label1, label2 FROM test WHERE id = 1'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Now the same with emulated PS. + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn on emulated prepared statements\n"); + printf("Emulated...\n"); + + $stmt = $db->prepare('INSERT INTO test(id, label1, label2) VALUES(2, :placeholder, :placeholder)'); + // No replacement shall be made + $stmt->execute(array(':placeholder' => 'row2')); + if ('00000' !== $stmt->errorCode()) + printf("[005] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + // Now, what do we have in the DB? + $stmt = $db->prepare('SELECT id, label1, label2 FROM test WHERE id = 2'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // + // Another variation of the theme + // + + $db->exec('DELETE FROM test'); + $db->exec("INSERT INTO test (id, label1, label2) VALUES (1, 'row1', 'row2')"); + $sql = "SELECT id, label1 FROM test WHERE id = :placeholder AND label1 = (SELECT label1 AS 'SELECT' FROM test WHERE id = :placeholder)"; + + // emulated... + $stmt = $db->prepare($sql); + $stmt->execute(array(':placeholder' => 1)); + if ('00000' !== $stmt->errorCode()) + printf("[006] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // native... + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[007] Unable to turn off emulated prepared statements\n"); + printf("Native...\n"); + + $stmt = $db->prepare($sql); + $stmt->execute(array(':placeholder' => 1)); + if ('00000' !== $stmt->errorCode()) + printf("[008] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_dup_named_placeholder.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_dup_named_placeholder.php.expectf new file mode 100644 index 000000000..217eec09b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_dup_named_placeholder.php.expectf @@ -0,0 +1,40 @@ +Native... +HipHop Warning: %a +[003] Execute has failed, 'HY093' array ( + 0 => 'HY093', + 1 => NULL, + 2 => NULL, +) +array(0) { +} +Emulated... +array(1) { + [0]=> + array(3) { + ["id"]=> + string(1) "2" + ["label1"]=> + string(4) "row2" + ["label2"]=> + string(4) "row2" + } +} +array(1) { + [0]=> + array(2) { + ["id"]=> + string(1) "1" + ["label1"]=> + string(4) "row1" + } +} +Native... +HipHop Warning: %a +[008] Execute has failed, 'HY093' array ( + 0 => 'HY093', + 1 => NULL, + 2 => NULL, +) +array(0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_mixed_style.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_mixed_style.php new file mode 100644 index 000000000..81956f51c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_mixed_style.php @@ -0,0 +1,21 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->query('DELETE FROM test'); + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (1, ?), (2, ?)'); + $stmt->execute(array('a', 'b')); + $stmt = $db->prepare("SELECT id, label FROM test WHERE id = :placeholder AND label = (SELECT label AS 'SELECT' FROM test WHERE id = ?)"); + $stmt->execute(array(1, 1)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_mixed_style.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_mixed_style.php.expectf new file mode 100644 index 000000000..97a857da0 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_mixed_style.php.expectf @@ -0,0 +1,3 @@ +HipHop Warning: %a +HipHop Warning: %a +HipHop Fatal error: %a \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_named_placeholder.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_named_placeholder.php new file mode 100644 index 000000000..c57b5d28c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_named_placeholder.php @@ -0,0 +1,62 @@ +exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + // INSERT a single row + $stmt = $db->prepare("INSERT INTO test(id, label) VALUES (100, ':placeholder')"); + + // Yes, there is no placeholder to bind to and named placeholder + // do not work with MySQL native PS, but lets see what happens! + // The ':placeholder' is a string constant in the INSERT statement. + // I would expect to get an error message, but this is not what happens. + $stmt->execute(array(':placeholder' => 'row1')); + if ('00000' !== $stmt->errorCode()) + printf("[003] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + // Ok, what has happened: anything inserted into the DB? + $stmt = $db->prepare('SELECT id, label FROM test'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // Now the same with emulated PS. + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn on emulated prepared statements\n"); + + // Note that the "named placeholder" is enclosed by double quotes. + $stmt = $db->prepare("INSERT INTO test(id, label) VALUES(101, ':placeholder')"); + // No replacement shall be made + $stmt->execute(array(':placeholder' => 'row1')); + // Again, I'd like to see an error message + if ('00000' !== $stmt->errorCode()) + printf("[005] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + // Now, what do we have in the DB? + $stmt = $db->prepare('SELECT id, label FROM test ORDER BY id'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_named_placeholder.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_named_placeholder.php.expectf new file mode 100644 index 000000000..fc7ade6bc --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_named_placeholder.php.expectf @@ -0,0 +1,17 @@ +[003] Execute has failed, 'HY093' array ( + 0 => 'HY093', + 1 => NULL, + 2 => NULL, +) +array(0) { +} +array(1) { + [0]=> + array(2) { + ["id"]=> + string(3) "101" + ["label"]=> + string(12) ":placeholder" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_placeholder_everywhere.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_placeholder_everywhere.php new file mode 100644 index 000000000..a7028c880 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_placeholder_everywhere.php @@ -0,0 +1,55 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to switch on emulated prepared statements, test will fail\n"); + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label CHAR(255)) ENGINE=%s', PDO_MYSQL_TEST_ENGINE)); + $db->exec("INSERT INTO test(id, label) VALUES (1, 'row1')"); + + $stmt = $db->prepare('SELECT ?, id, label FROM test WHERE ? = ? ORDER BY id ASC'); + $stmt->execute(array('id', 'label', 'label')); + if ('00000' !== $stmt->errorCode()) + printf("[003] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // now the same with native PS + printf("now the same with native PS\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to switch off emulated prepared statements, test will fail\n"); + + $stmt = $db->prepare('SELECT ?, id, label FROM test WHERE ? = ? ORDER BY id ASC'); + $stmt->execute(array('id', 'label', 'label')); + if ('00000' !== $stmt->errorCode()) + printf("[005] Execute has failed, %s %s\n", + var_export($stmt->errorCode(), true), + var_export($stmt->errorInfo(), true)); + + $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC); + if (!MySQLPDOTest::isPDOMySQLnd()) { + if (isset($tmp[0]['id'])) { + // libmysql should return a string here whereas mysqlnd returns a native int + if (gettype($tmp[0]['id']) == 'string') + // convert to int for the test output... + settype($tmp[0]['id'], 'integer'); + } + } + var_dump($tmp); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_placeholder_everywhere.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_placeholder_everywhere.php.expectf new file mode 100644 index 000000000..17019efad --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_prepare_native_placeholder_everywhere.php.expectf @@ -0,0 +1,22 @@ +array(1) { + [0]=> + array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(4) "row1" + } +} +now the same with native PS +array(1) { + [0]=> + array(3) { + ["?"]=> + string(2) "id" + ["id"]=> + int(1) + ["label"]=> + string(4) "row1" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_rollback.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_rollback.php new file mode 100644 index 000000000..3b90a5b0e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_rollback.php @@ -0,0 +1,76 @@ +beginTransaction(); + + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + $num = $row['_num']; + + $db->query("INSERT INTO test(id, label) VALUES (100, 'z')"); + $num++; + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[001] INSERT has failed, test will fail\n"); + + $db->rollBack(); + $num--; + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[002] ROLLBACK has failed\n"); + + $db->beginTransaction(); + $db->query("INSERT INTO test(id, label) VALUES (100, 'z')"); + $db->query('DROP TABLE IF EXISTS test2'); + $db->query('CREATE TABLE test2(id INT)'); + $num++; + $db->rollBack(); + $row = $db->query('SELECT COUNT(*) AS _num FROM test')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != $num) + printf("[002] ROLLBACK should have no effect because of the implicit COMMIT + triggered by DROP/CREATE TABLE\n"); + + + $db->query('DROP TABLE IF EXISTS test2'); + $db->query('CREATE TABLE test2(id INT) ENGINE=MyISAM'); + $db->beginTransaction(); + $db->query('INSERT INTO test2(id) VALUES (1)'); + $db->rollBack(); + $row = $db->query('SELECT COUNT(*) AS _num FROM test2')->fetch(PDO::FETCH_ASSOC); + if ($row['_num'] != 1) + printf("[003] ROLLBACK should have no effect\n"); + + $db->query('DROP TABLE IF EXISTS test2'); + + $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); + $db->beginTransaction(); + $db->query('DELETE FROM test'); + $db->rollBack(); + var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT)); + + $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 0); + $db->beginTransaction(); + $db->query('DELETE FROM test'); + $db->rollBack(); + var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT)); + + $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 1); + $db->beginTransaction(); + $db->query('DELETE FROM test'); + $db->commit(); + var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT)); + + $db->setAttribute(PDO::ATTR_AUTOCOMMIT, 0); + $db->beginTransaction(); + $db->query('DELETE FROM test'); + $db->commit(); + var_dump($db->getAttribute(PDO::ATTR_AUTOCOMMIT)); + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +$db->exec('DROP TABLE IF EXISTS test2'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_rollback.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_rollback.php.expectf new file mode 100644 index 000000000..d72303ff6 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_rollback.php.expectf @@ -0,0 +1,5 @@ +int(1) +int(0) +int(1) +int(0) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindcolumn.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindcolumn.php new file mode 100644 index 000000000..ba7f24cfe --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindcolumn.php @@ -0,0 +1,97 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id, label FROM test ORDER BY id ASC LIMIT 2'); + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[003] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[004] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $data = array(); + while ($stmt->fetch(PDO::FETCH_BOUND)) { + printf("id = %s (%s) / label = %s (%s)\n", + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + $data[] = array('id' => $id, 'label' => $label); + } + + $stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 2'); + $index = 0; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + if ($row['id'] != $data[$index]['id']) { + printf("[005] Fetch bound and fetch assoc differ - column 'id', bound: %s/%s, assoc: %s/%s\n", + var_export($data[$index]['id'], true), gettype($data[$index]['id']), + var_export($row['id'], true), gettype($row['id'])); + } + if ($row['label'] != $data[$index]['label']) { + printf("[006] Fetch bound and fetch assoc differ - column 'label', bound: %s/%s, assoc: %s/%s\n", + var_export($data[$index]['label'], true), gettype($data[$index]['label']), + var_export($row['label'], true), gettype($row['label'])); + } + $index++; + } + + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[007] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id, label FROM test ORDER BY id ASC LIMIT 2, 2'); + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[008] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[009] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $data = array(); + while ($stmt->fetch(PDO::FETCH_BOUND)) { + printf("id = %s (%s) / label = %s (%s)\n", + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + $data[] = array('id' => $id, 'label' => $label); + } + + $stmt = $db->query('SELECT id, label FROM test ORDER BY id ASC LIMIT 2, 2'); + $index = 0; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + if ($row['id'] != $data[$index]['id']) { + printf("[010] Fetch bound and fetch assoc differ - column 'id', bound: %s/%s, assoc: %s/%s\n", + var_export($data[$index]['id'], true), gettype($data[$index]['id']), + var_export($row['id'], true), gettype($row['id'])); + } + if ($row['label'] != $data[$index]['label']) { + printf("[011] Fetch bound and fetch assoc differ - column 'label', bound: %s/%s, assoc: %s/%s\n", + var_export($data[$index]['label'], true), gettype($data[$index]['label']), + var_export($row['label'], true), gettype($row['label'])); + } + $index++; + } + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindcolumn.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindcolumn.php.expectf new file mode 100644 index 000000000..ef9bfcca3 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindcolumn.php.expectf @@ -0,0 +1,5 @@ +id = 1 (integer) / label = 'a' (string) +id = 2 (integer) / label = 'b' (string) +id = 3 (integer) / label = 'c' (string) +id = 4 (integer) / label = 'd' (string) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam.php new file mode 100644 index 000000000..365bad6e3 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam.php @@ -0,0 +1,112 @@ +setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + + MySQLPDOTest::createTestTable($db); + + function pdo_mysql_stmt_bindparam($db, $offset) { + + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindParam(1, $in)) + printf("[%03d + 1] Cannot bind parameter, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[%03d + 2] Cannot bind integer column, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[%03d + 3] Cannot bind string column, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Same again...\n"); + $stmt->execute(); + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + // NULL values + printf("NULL...\n"); + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (100, ?)'); + $label = null; + if (!$stmt->bindParam(1, $label)) + printf("[%03d + 4] Cannot bind parameter, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->execute()) + printf("[%03d + 5] Cannot execute statement, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + /* NOTE: you cannot use PDO::query() with unbuffered, native PS - see extra test */ + $stmt = $db->prepare('SELECT id, NULL AS _label FROM test WHERE label IS NULL'); + $stmt->execute(); + + $id = $label = 'bogus'; + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[%03d + 6] Cannot bind NULL column, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[%03d + 3] Cannot bind string column, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + } + + try { + printf("Emulated PS...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + printf("Buffered...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + pdo_mysql_stmt_bindparam($db, 3); + + printf("Unbuffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + pdo_mysql_stmt_bindparam($db, 4); + + printf("Native PS...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn off emulated prepared statements\n"); + + printf("Buffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + pdo_mysql_stmt_bindparam($db, 5); + + printf("Unbuffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + pdo_mysql_stmt_bindparam($db, 6); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam.php.expectf new file mode 100644 index 000000000..2cf89af3e --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam.php.expectf @@ -0,0 +1,35 @@ +Emulated PS... +Buffered... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Same again... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +NULL... +in = 0 -> id = 100 (integer) / label = NULL (NULL) +Unbuffered... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Same again... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +NULL... +in = 0 -> id = 100 (integer) / label = NULL (NULL) +Native PS... +Buffered... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Same again... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +NULL... +in = 0 -> id = 100 (integer) / label = NULL (NULL) +Unbuffered... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Same again... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +NULL... +in = 0 -> id = 100 (integer) / label = NULL (NULL) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam_types.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam_types.php new file mode 100644 index 000000000..556256b5c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam_types.php @@ -0,0 +1,159 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + else + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + + $db->exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); + if ((!$stmt = @$db->prepare($sql)) || (!@$stmt->execute())) + // Server might not support column type - skip it + return true; + + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (1, ?)'); + if (!$stmt->bindParam(1, $value)) { + printf("[%03d/%s + 1] %s\n", $offset, ($native) ? 'native' : 'emulated', + var_export($stmt->errorInfo(), true)); + return false; + } + if (!$stmt->execute()) { + printf("[%03d/%s + 2] %s\n", $offset, ($native) ? 'native' : 'emulated', + var_export($stmt->errorInfo(), true)); + return false; + } + + $stmt = $db->query('SELECT id, label FROM test'); + $id = $label = null; + if (!$stmt->bindColumn(1, $id)) { + printf("[%03d/%s + 3] %s\n", $offset, ($native) ? 'native' : 'emulated', + var_export($stmt->errorInfo(), true)); + return false; + } + if (!$stmt->bindColumn(2, $label)) { + printf("[%03d/%s + 4] %s\n", $offset, ($native) ? 'native' : 'emulated', + var_export($stmt->errorInfo(), true)); + return false; + } + + if (!$stmt->fetch(PDO::FETCH_BOUND)) { + printf("[%03d/%s + 5] %s\n", $offset, ($native) ? 'native' : 'emulated', + var_export($stmt->errorInfo(), true)); + return false; + } + $stmt->closeCursor(); + + if ($label != $value) { + printf("[%03d/%s + 6] Got %s expecting %s - plase check manually\n", + $offset, ($native) ? 'native' : 'emulated', + var_export($label, true), var_export($value, true)); + // fall through + } + + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + if (empty($row)) { + printf("[%03d/%s + 7] %s\n", $offset, ($native) ? 'native' : 'emulated', + var_export($stmt->errorInfo(), true)); + return false; + } + + if ($row['label'] != $value) { + printf("[%03d/%s + 8] Got %s expecting %s - plase check manually\n", + $offset, ($native) ? 'native' : 'emulated', + var_export($row['label'], true), var_export($value, true)); + return false; + } + + if ($row['label'] != $label) { + printf("[%03d/%s + 9] Got %s from FETCH_ASSOC and %s from FETCH_BOUND- plase check manually\n", + $offset, ($native) ? 'native' : 'emulated', + var_export($row['label'], true), var_export($value, true)); + return false; + } + + $db->exec('DROP TABLE IF EXISTS test'); + return true; + } + + function pdo_mysql_stmt_bindparam_types($db, $offset, $sql_type, $value) { + + pdo_mysql_stmt_bindparam_types_do($db, $offset, true, $sql_type, $value); + pdo_mysql_stmt_bindparam_types_do($db, $offset, false, $sql_type, $value); + + } + + try { + + // pdo_mysql_stmt_bindparam_types($db, 2, 'BIT(8)', 1); + pdo_mysql_stmt_bindparam_types($db, 3, 'TINYINT', -127); + pdo_mysql_stmt_bindparam_types($db, 4, 'TINYINT UNSIGNED', 255); + pdo_mysql_stmt_bindparam_types($db, 5, 'BOOLEAN', 1); + pdo_mysql_stmt_bindparam_types($db, 6, 'SMALLINT', -32768); + pdo_mysql_stmt_bindparam_types($db, 7, 'SMALLINT UNSIGNED', 65535); + pdo_mysql_stmt_bindparam_types($db, 8, 'MEDIUMINT', -8388608); + pdo_mysql_stmt_bindparam_types($db, 9, 'MEDIUMINT UNSIGNED', 16777215); + pdo_mysql_stmt_bindparam_types($db, 10, 'INT', -2147483648); + pdo_mysql_stmt_bindparam_types($db, 11, 'INT UNSIGNED', 4294967295); + pdo_mysql_stmt_bindparam_types($db, 12, 'BIGINT', -1000); + pdo_mysql_stmt_bindparam_types($db, 13, 'BIGINT UNSIGNED', 1000); + pdo_mysql_stmt_bindparam_types($db, 14, 'REAL', -1000); + pdo_mysql_stmt_bindparam_types($db, 15, 'REAL UNSIGNED', 1000); + pdo_mysql_stmt_bindparam_types($db, 16, 'REAL ZEROFILL', '0000000000000000000000'); + pdo_mysql_stmt_bindparam_types($db, 17, 'REAL UNSIGNED ZEROFILL', '0000000000000000000010'); + pdo_mysql_stmt_bindparam_types($db, 18, 'DOUBLE', -1000); + pdo_mysql_stmt_bindparam_types($db, 19, 'DOUBLE UNSIGNED', 1000); + pdo_mysql_stmt_bindparam_types($db, 20, 'DOUBLE ZEROFILL', '000000000000'); + pdo_mysql_stmt_bindparam_types($db, 21, 'DOUBLE ZEROFILL UNSIGNED', '000000001000'); + pdo_mysql_stmt_bindparam_types($db, 22, 'FLOAT', -1000); + pdo_mysql_stmt_bindparam_types($db, 23, 'FLOAT UNSIGNED', 1000); + pdo_mysql_stmt_bindparam_types($db, 24, 'FLOAT ZEROFILL', '000000000000'); + pdo_mysql_stmt_bindparam_types($db, 25, 'FLOAT ZEROFILL UNSIGNED', '000000001000'); + pdo_mysql_stmt_bindparam_types($db, 26, 'DECIMAL', -1000); + pdo_mysql_stmt_bindparam_types($db, 27, 'DECIMAL UNSIGNED', 1000); + pdo_mysql_stmt_bindparam_types($db, 28, 'DECIMAL ZEROFILL', '000000000000'); + pdo_mysql_stmt_bindparam_types($db, 29, 'DECIMAL ZEROFILL UNSIGNED', '000000001000'); + pdo_mysql_stmt_bindparam_types($db, 30, 'NUMERIC', -1000); + pdo_mysql_stmt_bindparam_types($db, 31, 'NUMERIC UNSIGNED', 1000); + pdo_mysql_stmt_bindparam_types($db, 32, 'NUMERIC ZEROFILL', '000000000000'); + pdo_mysql_stmt_bindparam_types($db, 33, 'NUMERIC ZEROFILL UNSIGNED', '000000001000'); + pdo_mysql_stmt_bindparam_types($db, 34, 'DATE', '2008-04-23'); + pdo_mysql_stmt_bindparam_types($db, 35, 'TIME', '16:43:12'); + pdo_mysql_stmt_bindparam_types($db, 36, 'TIMESTAMP', '2008-04-23 16:44:53'); + pdo_mysql_stmt_bindparam_types($db, 37, 'DATETIME', '2008-04-23 16:44:53'); + pdo_mysql_stmt_bindparam_types($db, 38, 'YEAR', '2008'); + pdo_mysql_stmt_bindparam_types($db, 39, 'CHAR(1)', 'a'); + pdo_mysql_stmt_bindparam_types($db, 40, 'CHAR(255)', 'abc'); + pdo_mysql_stmt_bindparam_types($db, 41, 'VARCHAR(255)', str_repeat('a', 255)); + pdo_mysql_stmt_bindparam_types($db, 42, 'BINARY(255)', str_repeat('a', 255)); + pdo_mysql_stmt_bindparam_types($db, 43, 'VARBINARY(255)', str_repeat('a', 255)); + pdo_mysql_stmt_bindparam_types($db, 44, 'TINYBLOB', str_repeat('a', 255)); + pdo_mysql_stmt_bindparam_types($db, 45, 'BLOB', str_repeat('b', 300)); + pdo_mysql_stmt_bindparam_types($db, 46, 'MEDIUMBLOB', str_repeat('b', 300)); + pdo_mysql_stmt_bindparam_types($db, 47, 'LONGBLOB', str_repeat('b', 300)); + pdo_mysql_stmt_bindparam_types($db, 48, 'TINYTEXT', str_repeat('c', 255)); + pdo_mysql_stmt_bindparam_types($db, 49, 'TINYTEXT BINARY', str_repeat('c', 255)); + pdo_mysql_stmt_bindparam_types($db, 50, 'TEXT', str_repeat('d', 300)); + pdo_mysql_stmt_bindparam_types($db, 51, 'TEXT BINARY', str_repeat('d', 300)); + pdo_mysql_stmt_bindparam_types($db, 52, 'MEDIUMTEXT', str_repeat('d', 300)); + pdo_mysql_stmt_bindparam_types($db, 53, 'MEDIUMTEXT BINARY', str_repeat('d', 300)); + pdo_mysql_stmt_bindparam_types($db, 54, 'LONGTEXT', str_repeat('d', 300)); + pdo_mysql_stmt_bindparam_types($db, 55, 'LONGTEXT BINARY', str_repeat('d', 300)); + pdo_mysql_stmt_bindparam_types($db, 56, "ENUM('yes', 'no') DEFAULT 'yes'", "no"); + pdo_mysql_stmt_bindparam_types($db, 57, "SET('yes', 'no') DEFAULT 'yes'", "no"); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam_types.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam_types.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindparam_types.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindvalue.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindvalue.php new file mode 100644 index 000000000..4af6312d0 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindvalue.php @@ -0,0 +1,290 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + printf("Binding variable...\n"); + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindValue(1, $in)) + printf("[003] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[004] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[005] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Binding value and not variable...\n"); + if (!$stmt->bindValue(1, 0)) + printf("[006] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[007] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[008] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Binding variable which references another variable...\n"); + $in = 0; + $in_ref = &$in; + if (!$stmt->bindValue(1, $in_ref)) + printf("[009] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[010] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[011] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + + printf("Binding a variable and a value...\n"); + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? AND id <= ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindValue(1, $in)) + printf("[012] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindValue(2, 2)) + printf("[013] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[014] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[015] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Binding a variable to two placeholders and changing the variable value in between the binds...\n"); + // variable value change shall have no impact + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? AND id <= ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindValue(1, $in)) + printf("[016] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $in = 2; + if (!$stmt->bindValue(2, $in)) + printf("[017] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[018] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[019] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + printf("Testing emulated PS...\n"); + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + printf("Binding variable...\n"); + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindValue(1, $in)) + printf("[003] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[004] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[005] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Binding value and not variable...\n"); + if (!$stmt->bindValue(1, 0)) + printf("[006] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[007] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[008] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Binding variable which references another variable...\n"); + $in = 0; + $in_ref = &$in; + if (!$stmt->bindValue(1, $in_ref)) + printf("[009] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[010] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[011] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + + printf("Binding a variable and a value...\n"); + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? AND id <= ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindValue(1, $in)) + printf("[012] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindValue(2, 2)) + printf("[013] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[014] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[015] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + printf("Binding a variable to two placeholders and changing the variable value in between the binds...\n"); + // variable value change shall have no impact + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? AND id <= ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindValue(1, $in)) + printf("[016] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $in = 2; + if (!$stmt->bindValue(2, $in)) + printf("[017] Cannot bind value, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[018] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[019] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindvalue.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindvalue.php.expectf new file mode 100644 index 000000000..d25feef0b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_bindvalue.php.expectf @@ -0,0 +1,33 @@ +Testing native PS... +Binding variable... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding value and not variable... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding variable which references another variable... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding a variable and a value... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding a variable to two placeholders and changing the variable value in between the binds... +in = 2 -> id = 1 (integer) / label = 'a' (string) +in = 2 -> id = 2 (integer) / label = 'b' (string) +Testing emulated PS... +Binding variable... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding value and not variable... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding variable which references another variable... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding a variable and a value... +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Binding a variable to two placeholders and changing the variable value in between the binds... +in = 2 -> id = 1 (integer) / label = 'a' (string) +in = 2 -> id = 2 (integer) / label = 'b' (string) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobfromsteam.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobfromsteam.php new file mode 100644 index 000000000..4cbd2f673 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobfromsteam.php @@ -0,0 +1,113 @@ +exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label BLOB) ENGINE=%s', PDO_MYSQL_TEST_ENGINE); + $db->exec($sql); + + if (!$stmt = $db->prepare('INSERT INTO test(id, label) VALUES (?, ?)')) { + printf("[%03d + 4] %s\n", $offset, var_export($db->errorInfo(), true)); + return false; + } + + $fp = fopen($file, 'r'); + if (!$fp) { + printf("[%03d + 5] Cannot create test file '%s'\n", $offset, $file); + return false; + } + + + $id = 1; + $stmt->bindParam(1, $id); + if (true !== ($tmp = $stmt->bindParam(2, $fp, PDO::PARAM_LOB))) { + printf("[%03d + 6] Expecting true, got %s. %s\n", + $offset, + var_export($tmp, true), + var_export($db->errorInfo(), true)); + return false; + } + + if (true !== $stmt->execute()) { + printf("[%03d + 7] Failed to INSERT data, %s\n", $offset, var_export($stmt->errorInfo(), true)); + return false; + } + + $stmt2 = $db->query('SELECT id, label FROM test WHERE id = 1'); + $row = $stmt2->fetch(PDO::FETCH_ASSOC); + if ($row['label'] != $blob) { + printf("[%03d + 8] INSERT and/or SELECT has failed, dumping data.\n", $offset); + var_dump($row); + var_dump($blob); + return false; + } + + // Lets test the chr(0) handling in case the streaming has failed: + // is the bug about chr(0) or the streaming... + $db->exec('DELETE FROM test'); + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (?, ?)'); + $stmt->bindParam(1, $id); + $stmt->bindParam(2, $blob); + if (true !== $stmt->execute()) + printf("[%03d + 9] %s\n", $offset, var_export($stmt->errorInfo(), true)); + + $stmt2 = $db->query('SELECT id, label FROM test WHERE id = 1'); + $row = $stmt2->fetch(PDO::FETCH_ASSOC); + if ($row['label'] != $blob) { + printf("[%03d + 10] INSERT and/or SELECT has failed, dumping data.\n", $offset); + var_dump($row); + var_dump($blob); + return false; + } + + return true; + } + + $db = MySQLPDOTest::factory(); + $blob = 'I am a mighty BLOB!' . chr(0) . "I am a binary thingie!"; + $tmp = MySQLPDOTest::getTempDir(); + $file = $tmp . DIRECTORY_SEPARATOR . 'pdoblob.tst'; + + try { + + printf("Emulated PS...\n"); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + blob_from_stream(10, $db, $file, $blob); + + printf("Native PS...\n"); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + blob_from_stream(30, $db, $file, $blob); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +@unlink(MySQLPDOTest::getTempDir() . DIRECTORY_SEPARATOR . 'pdoblob.tst'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobfromsteam.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobfromsteam.php.expectf new file mode 100644 index 000000000..f0181886a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobfromsteam.php.expectf @@ -0,0 +1,3 @@ +Emulated PS... +Native PS... +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobs.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobs.php new file mode 100644 index 000000000..7b4f4aa33 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobs.php @@ -0,0 +1,85 @@ + 255, + 'TINYTEXT' => 255, + 'BLOB' => 32767, + 'TEXT' => 32767, + 'MEDIUMBLOB' => 100000, + 'MEDIUMTEXT' => 100000, + 'LONGBLOB' => 100000, + 'LONGTEXT' => 100000, + ); + + function test_blob($db, $offset, $sql_type, $test_len) { + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, PDO_MYSQL_TEST_ENGINE)); + + $value = str_repeat('a', $test_len); + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (?, ?)'); + $stmt->bindValue(1, 1); + $stmt->bindValue(2, $value); + if (!$stmt->execute()) { + printf("[%03d + 1] %d %s\n", + $offset, $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + return false; + } + + $stmt = $db->query('SELECT id, label FROM test'); + $id = $label = NULL; + $stmt->bindColumn(1, $id, PDO::PARAM_INT); + $stmt->bindColumn(2, $label, PDO::PARAM_LOB); + + if (!$stmt->fetch(PDO::FETCH_BOUND)) { + printf("[%03d + 2] %d %s\n", + $offset, $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + return false; + } + + if ($label !== $value) { + printf("[%03d + 3] Returned value seems to be wrong (%d vs. %d charachters). Check manually\n", + $offset, strlen($label), strlen($value)); + return false; + } + + if (1 != $id) { + printf("[%03d + 3] Returned id column value seems wrong, expecting 1 got %s.\n", + $offset, var_export($id, true)); + return false; + } + + $stmt = $db->query('SELECT id, label FROM test'); + $ret = $stmt->fetch(PDO::FETCH_ASSOC); + + if ($ret['label'] !== $value) { + printf("[%03d + 3] Returned value seems to be wrong (%d vs. %d charachters). Check manually\n", + $offset, strlen($ret['label']), strlen($value)); + return false; + } + + if (1 != $ret['id']) { + printf("[%03d + 3] Returned id column value seems wrong, expecting 1 got %s.\n", + $offset, var_export($ret['id'], true)); + return false; + } + + return true; + } + + $offset = 0; + foreach ($blobs as $sql_type => $test_len) { + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + test_blob($db, ++$offset, $sql_type, $test_len); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + test_blob($db, ++$offset, $sql_type, $test_len); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobs.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobs.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_blobs.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor.php new file mode 100644 index 000000000..95aad1c55 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor.php @@ -0,0 +1,140 @@ +setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $stmt1 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + // query() shall fail! + $stmt2 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + $stmt1->closeCursor(); + + // This is proper usage of closeCursor(). It shall prevent any further error messages. + if (MySQLPDOTest::isPDOMySQLnd()) { + $stmt1 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + } else { + // see pdo_mysql_stmt_unbuffered_2050.phpt for an explanation + unset($stmt1); + $stmt1 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + } + // fetch only the first rows and let closeCursor() clean up + $row1 = $stmt1->fetch(PDO::FETCH_ASSOC); + $stmt1->closeCursor(); + + $stmt2 = $db->prepare('UPDATE test SET label = ? WHERE id = ?'); + $stmt2->bindValue(1, "z"); + + $stmt2->bindValue(2, $row1['id']); + $stmt2->execute(); + $stmt2->closeCursor(); + + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + // check if changing the fetch mode from unbuffered to buffered will + // cause any harm to a statement created prior to the change + $stmt1->execute(); + $row2 = $stmt1->fetch(PDO::FETCH_ASSOC); + $stmt1->closeCursor(); + if (!isset($row2['label']) || ('z' !== $row2['label'])) + printf("Expecting array(id => 1, label => z) got %s\n", var_export($row2, true)); + unset($stmt1); + + $stmt1 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + // should work + $stmt2 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + $stmt1->closeCursor(); + + $stmt1 = $db->query('SELECT id, label FROM test ORDER BY id ASC'); + // fetch only the first rows and let closeCursor() clean up + $row3 = $stmt1->fetch(PDO::FETCH_ASSOC); + $stmt1->closeCursor(); + assert($row3 == $row2); + + $stmt2 = $db->prepare('UPDATE test SET label = ? WHERE id = ?'); + $stmt2->bindValue(1, "a"); + $stmt2->bindValue(2, $row1['id']); + $stmt2->execute(); + $stmt2->closeCursor(); + + $stmt1->execute(); + $row4 = $stmt1->fetch(PDO::FETCH_ASSOC); + $stmt1->closeCursor(); + assert($row4 == $row1); + + $offset = 0; + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindParam(1, $in)) + printf("[%03d + 1] Cannot bind parameter, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[%03d + 2] Cannot bind integer column, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[%03d + 3] Cannot bind string column, %s %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + $stmt->closeCursor(); + $stmt->execute(); + + } + + + try { + + printf("Testing emulated PS...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + printf("Buffered...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + MySQLPDOTest::createTestTable($db); + pdo_mysql_stmt_closecursor($db); + + printf("Unbuffered...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + MySQLPDOTest::createTestTable($db); + pdo_mysql_stmt_closecursor($db); + + printf("Testing native PS...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + printf("Buffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + pdo_mysql_stmt_closecursor($db); + + printf("Unbuffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + pdo_mysql_stmt_closecursor($db); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor.php.expectf new file mode 100644 index 000000000..3dbd9a048 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor.php.expectf @@ -0,0 +1,19 @@ +Testing emulated PS... +Buffered... +HipHop Warning: %a +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Unbuffered... +HipHop Warning: %a +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Testing native PS... +Buffered... +HipHop Warning: %a +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +Unbuffered... +HipHop Warning: %a +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor_empty.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor_empty.php new file mode 100644 index 000000000..67dbf6d1d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor_empty.php @@ -0,0 +1,56 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + MySQLPDOTest::createTestTable($db); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE id > ? ORDER BY id ASC LIMIT 2'); + $in = 0; + if (!$stmt->bindParam(1, $in)) + printf("[003] Cannot bind parameter, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + $stmt->execute(); + $id = $label = null; + + if (!$stmt->bindColumn(1, $id, PDO::PARAM_INT)) + printf("[004] Cannot bind integer column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + if (!$stmt->bindColumn(2, $label, PDO::PARAM_STR)) + printf("[005] Cannot bind string column, %s %s\n", + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + $stmt->closeCursor(); + $stmt->execute(); + while ($stmt->fetch(PDO::FETCH_BOUND)) + printf("in = %d -> id = %s (%s) / label = %s (%s)\n", + $in, + var_export($id, true), gettype($id), + var_export($label, true), gettype($label)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + $db->exec('DROP TABLE IF EXISTS test'); + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor_empty.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor_empty.php.expectf new file mode 100644 index 000000000..df8b66792 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_closecursor_empty.php.expectf @@ -0,0 +1,5 @@ +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +in = 0 -> id = 1 (integer) / label = 'a' (string) +in = 0 -> id = 2 (integer) / label = 'b' (string) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_columncount.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_columncount.php new file mode 100644 index 000000000..6d1cf27eb --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_columncount.php @@ -0,0 +1,49 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + $stmt = $db->prepare("SELECT id, label, '?' as foo FROM test"); + $stmt->execute(); + var_dump($stmt->columnCount()); + + $stmt = $db->query('SELECT * FROM test'); + var_dump($stmt->columnCount()); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + printf("Testing native PS...\n"); + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare("SELECT id, label, '?' as foo, 'TODO - Stored Procedure' as bar FROM test"); + $stmt->execute(); + var_dump($stmt->columnCount()); + + $stmt = $db->query('SELECT * FROM test'); + var_dump($stmt->columnCount()); + + } catch (PDOException $e) { + printf("[003] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_columncount.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_columncount.php.expectf new file mode 100644 index 000000000..6403fa9fb --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_columncount.php.expectf @@ -0,0 +1,7 @@ +Testing emulated PS... +int(3) +int(2) +Testing native PS... +int(4) +int(2) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorcode.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorcode.php new file mode 100644 index 000000000..b39c06601 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorcode.php @@ -0,0 +1,39 @@ +exec('DROP TABLE IF EXISTS ihopeitdoesnotexist'); + + printf("Testing emulated PS...\n"); + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id FROM ihopeitdoesnotexist ORDER BY id ASC'); + $stmt->execute(); + var_dump($stmt->errorCode()); + + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + printf("Testing native PS...\n"); + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id FROM ihopeitdoesnotexist ORDER BY id ASC'); + $stmt->execute(); + var_dump($stmt->errorCode()); + + } catch (PDOException $e) { + printf("[003] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorcode.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorcode.php.expectf new file mode 100644 index 000000000..192e3574d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorcode.php.expectf @@ -0,0 +1,6 @@ +Testing emulated PS... +HipHop Warning: %a +string(5) "42S02" +Testing native PS... +HipHop Warning: %a +HipHop Fatal error: %a \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorinfo.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorinfo.php new file mode 100644 index 000000000..51f2e20fc --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorinfo.php @@ -0,0 +1,54 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id FROM ihopeitdoesnotexist ORDER BY id ASC'); + var_dump($stmt->errorInfo()); + $stmt->execute(); + var_dump($stmt->errorInfo()); + + MySQLPDOTest::createTestTable($db); + $stmt = $db->prepare('SELECT label FROM test ORDER BY id ASC LIMIT 1'); + $db->exec('DROP TABLE test'); + var_dump($stmt->execute()); + var_dump($stmt->errorInfo()); + var_dump($db->errorInfo()); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo())); + } + + printf("Testing native PS...\n"); + try { + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id FROM ihopeitdoesnotexist ORDER BY id ASC'); + var_dump($stmt); + + MySQLPDOTest::createTestTable($db); + $stmt = $db->prepare('SELECT label FROM test ORDER BY id ASC LIMIT 1'); + var_dump($stmt->errorInfo()); + $db->exec('DROP TABLE test'); + $stmt->execute(); + var_dump($stmt->errorInfo()); + var_dump($db->errorInfo()); + + } catch (PDOException $e) { + printf("[003] %s [%s] %s\n", + $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo())); + } + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorinfo.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorinfo.php.expectf new file mode 100644 index 000000000..08c1404c1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_errorinfo.php.expectf @@ -0,0 +1,65 @@ +Testing emulated PS... +array(3) { + [0]=> + %unicode|string%(0) "" + [1]=> + NULL + [2]=> + NULL +} +HipHop Warning: %a +array(3) { + [0]=> + %unicode|string%(5) "42S02" + [1]=> + int(1146) + [2]=> + %unicode|string%(%d) "Table '%s.ihopeitdoesnotexist' doesn't exist" +} +HipHop Warning: %a +bool(false) +array(3) { + [0]=> + %unicode|string%(5) "42S02" + [1]=> + int(1146) + [2]=> + %unicode|string%(%d) "Table '%s.test' doesn't exist" +} +array(3) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + NULL + [2]=> + NULL +} +Testing native PS... +HipHop Warning: %a +bool(false) +array(3) { + [0]=> + %unicode|string%(0) "" + [1]=> + NULL + [2]=> + NULL +} +HipHop Warning: %a +array(3) { + [0]=> + %unicode|string%(5) "42S02" + [1]=> + int(1146) + [2]=> + %unicode|string%(%d) "Table '%s.test' doesn't exist" +} +array(3) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + int(1146) + [2]=> + %unicode|string%(%d) "Table '%s.ihopeitdoesnotexist' doesn't exist" +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_non_select.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_non_select.php new file mode 100644 index 000000000..ba62bf468 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_non_select.php @@ -0,0 +1,178 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 1); + if (1 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn on emulated prepared statements\n"); + + if (!is_object($stmt = $db->query('DESCRIBE test id'))) + printf("[003] Emulated PS, DESCRIBE failed, %s\n", var_export($db->errorInfo(), true)); + + $describe = array(); + $valid = false; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $describe[] = $row; + foreach ($row as $column => $value) + if (isset($row['field']) && ($row['field'] == 'id')) + $valid = true; + } + if (empty($describe)) + printf("[004] Emulated PS, DESCRIBE returned no results\n"); + else if (!$valid) + printf("[005] Emulated PS, DESCRIBE, returned data seems wrong, dumping %s\n", + var_export($describe, true)); + + if (!is_object($stmt = $db->query('SHOW ENGINES'))) + printf("[006] Emulated PS, SHOW failed, %s\n", var_export($db->errorInfo(), true)); + + $show = array(); + $valid = false; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $show[] = $row; + foreach ($row as $column => $value) + // MyISAM engine should be part of _every_ MySQL today + if ($value == 'MyISAM') + $valid = true; + } + if (empty($show)) + printf("[007] Emulated PS, SHOW returned no results\n"); + else if (!$valid) + printf("[008] Emulated PS, SHOW data seems wrong, dumping %s\n", + var_export($show, true)); + + if (!is_object($stmt = $db->query("EXPLAIN SELECT id FROM test"))) + printf("[009] Emulated PS, EXPLAIN returned no results\n"); + + $explain = array(); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) + $explain[] = $row; + + if (empty($explain)) + printf("[010] Emulated PS, EXPLAIN returned no results\n"); + + // And now native PS + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[011] Unable to turn off emulated prepared statements\n"); + + $native_support = 'no'; + if ($db->exec("PREPARE mystmt FROM 'DESCRIBE test id'")) { + $native_support = 'yes'; + $db->exec('DEALLOCATE PREPARE mystmt'); + } + + if (!is_object($stmt = $db->query('DESCRIBE test id'))) + printf("[012] Native PS (native support: %s), DESCRIBE failed, %s\n", + $native_support, + var_export($db->errorInfo(), true)); + + $describe_native = array(); + $valid = false; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $describe_native[] = $row; + foreach ($row as $column => $value) + if (isset($row['field']) && ($row['field'] == 'id')) + $valid = true; + } + if (empty($describe_native)) + printf("[013] Native PS (native support: %s), DESCRIBE returned no results\n", + $native_support); + else if (!$valid) + printf("[014] Native PS (native support: %s), DESCRIBE, returned data seems wrong, dumping %s\n", + $native_support, + var_export($describe_native, true)); + + if ($describe != $describe_native) + printf("[015] Emulated and native PS (native support: %s) results of DESCRIBE differ: %s vs. %s\n", + $native_support, + var_export($describe, true), + var_export($describe_native, true)); + + + $native_support = 'no'; + if ($db->exec("PREPARE mystmt FROM 'SHOW ENGINES'")) { + $native_support = 'yes'; + $db->exec('DEALLOCATE PREPARE mystmt'); + } + + if (!is_object($stmt = $db->query('SHOW ENGINES'))) + printf("[016] Native PS (native support: %s), SHOW failed, %s\n", + $native_support, + var_export($db->errorInfo(), true)); + + $show_native = array(); + $valid = false; + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $show_native[] = $row; + foreach ($row as $column => $value) + // MyISAM engine should be part of _every_ MySQL today + if ($value == 'MyISAM') + $valid = true; + } + if (empty($show_native)) + printf("[017] Native PS (native support: %s), SHOW returned no results\n", + $native_support); + else if (!$valid) + printf("[018] Native PS (native support: %s), SHOW data seems wrong, dumping %s\n", + var_export($show_native, true)); + + if ($show != $show_native) + printf("Native PS (native support: %s) and emulated PS returned different data for SHOW: %s vs. %s\n", + $native_support, + var_export($show, true), + var_export($show_native, true)); + + $native_support = 'no'; + if ($db->exec("PREPARE mystmt FROM 'EXPLAIN SELECT id FROM test'")) { + $native_support = 'yes'; + $db->exec('DEALLOCATE PREPARE mystmt'); + } + + if (!is_object($stmt = $db->query("EXPLAIN SELECT id FROM test"))) + printf("[012] Native PS (native support: %s), EXPLAIN failed, %s\n", + $native_support, + var_export($db->errorInfo(), true)); + + $explain_native = array(); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) + $explain_native[] = $row; + + if (empty($explain_native)) + printf("[013] Native PS (native support: %s), EXPLAIN returned no results\n", + $native_support); + + if ($explain != $explain_native) + printf("Native PS (native support: %s) and emulated PS returned different data for EXPLAIN: %s vs. %s\n", + $native_support, + var_export($explain, true), + var_export($explain_native, true)); + + $stmt->execute(); + $explain_native = $stmt->fetchAll(PDO::FETCH_ASSOC); + if ($explain != $explain_native) + printf("Native PS (native support: %s) and emulated PS returned different data for EXPLAIN: %s vs. %s\n", + $native_support, + var_export($explain, true), + var_export($explain_native, true)); + + $stmt->execute(); + $stmt->execute(); + // libmysql needs this - otherwise we get a 2015 error + if (!MYSQLPDOTest::isPDOMySQLnd()) + $stmt->fetchAll(PDO::FETCH_ASSOC); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!\n"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_non_select.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_non_select.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_non_select.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize.php new file mode 100644 index 000000000..212486f65 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize.php @@ -0,0 +1,110 @@ +{$prop} = $value; + } + + public function __get($prop) { + printf("%s(%s)\n", __METHOD__, $prop); + return NULL; + } + + // Singleton + public static function singleton($caller) { + printf("%s(%s)\n", __METHOD__, $caller); + + if (!self::$instance) { + $c = __CLASS__; + self::$instance = new $c($caller); + } + return self::$instance; + } + + // Serializable + public function serialize() { + printf("%s()\n", __METHOD__); + return 'Data from serialize'; + } + + public function unserialize($data) { + printf("%s(%s)\n", __METHOD__, var_export($data, true)); + } + + } + + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[002] Unable to turn off emulated prepared statements\n"); + + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(id INT, myobj BLOB) ENGINE=%s', + MySQLPDOTest::getTableEngine())); + + printf("Creating an object, serializing it and writing it to DB...\n"); + $id = 1; + $obj = myclass::singleton('Creating object'); + $myobj = serialize($obj); + $stmt = $db->prepare('INSERT INTO test(id, myobj) VALUES (?, ?)'); + $stmt->bindValue(1, $id); + $stmt->bindValue(2, $myobj); + $stmt->execute(); + + printf("\nUnserializing the previously serialized object...\n"); + var_dump(unserialize($myobj)); + + printf("\nUsing PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE to fetch the object from DB and unserialize it...\n"); + $stmt = $db->prepare('SELECT myobj FROM test'); + $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE, 'myclass', array('PDO shall not call __construct()')); + $stmt->execute(); + var_dump($stmt->fetch()); + + printf("\nUsing PDO::FETCH_CLASS to fetch the object from DB and unserialize it...\n"); + $stmt = $db->prepare('SELECT myobj FROM test'); + $stmt->setFetchMode(PDO::FETCH_CLASS, 'myclass', array('PDO shall call __construct()')); + $stmt->execute(); + var_dump($stmt->fetch()); + + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!\n"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize.php.expectf new file mode 100644 index 000000000..8ffde00bf --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize.php.expectf @@ -0,0 +1,29 @@ +Creating an object, serializing it and writing it to DB... +myclass::singleton(Creating object) +myclass::__construct(Creating object) +myclass::serialize() + +Unserializing the previously serialized object... +myclass::unserialize('Data from serialize') +object(myclass)#4 (1) { + [%u|b%"myprotected":protected]=> + %unicode|string%(19) "a protected propery" +} + +Using PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE to fetch the object from DB and unserialize it... +myclass::unserialize('C:7:"myclass":19:{Data from serialize}') +object(myclass)#%d (1) { + [%u|b%"myprotected":protected]=> + %unicode|string%(19) "a protected propery" +} + +Using PDO::FETCH_CLASS to fetch the object from DB and unserialize it... +myclass::__set(myobj, 'C:7:"myclass":19:{Data from serialize}') +myclass::__construct(PDO shall call __construct()) +object(myclass)#%d (2) { + [%u|b%"myprotected":protected]=> + %unicode|string%(19) "a protected propery" + [%u|b%"myobj"]=> + %unicode|string%(38) "C:7:"myclass":19:{Data from serialize}" +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize_simple.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize_simple.php new file mode 100644 index 000000000..1ad154b7f --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize_simple.php @@ -0,0 +1,61 @@ +{$prop} = $value; + } + + public function serialize() { + printf("%s()\n", __METHOD__); + return 'Value from serialize()'; + } + + public function unserialize($data) { + printf("%s(%s)\n", __METHOD__, var_export($data, true)); + } + + } + + printf("Lets see what the Serializeable interface makes our object behave like...\n"); + $obj = new myclass('Called by script'); + $tmp = unserialize(serialize($obj)); + var_dump($tmp); + + printf("\nAnd now magic PDO using fetchAll(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE)...\n"); + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec(sprintf('CREATE TABLE test(myobj BLOB) ENGINE=%s', MySQLPDOTest::getTableEngine())); + $db->exec("INSERT INTO test(myobj) VALUES ('Data fetched from DB to be given to unserialize()')"); + + $stmt = $db->prepare('SELECT myobj FROM test'); + $stmt->execute(); + $rows = $stmt->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE, 'myclass', array('Called by PDO')); + var_dump($rows[0]); + + $stmt->execute(); + $rows = $stmt->fetchAll(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE, 'myclass'); + var_dump($rows[0]); + + printf("\nAnd now PDO using setFetchMode(PDO::FETCH:CLASS|PDO::FETCH_SERIALIZE) + fetch()...\n"); + $stmt = $db->prepare('SELECT myobj FROM test'); + $stmt->setFetchMode(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE, 'myclass', array('Called by PDO')); + $stmt->execute(); + var_dump($stmt->fetch()); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + $db->exec('DROP TABLE IF EXISTS test'); + print "done!\n"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize_simple.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize_simple.php.expectf new file mode 100644 index 000000000..76325672b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetch_serialize_simple.php.expectf @@ -0,0 +1,20 @@ +Lets see what the Serializeable interface makes our object behave like... +myclass::__construct('Called by script') - note that it must not be called when unserializing +myclass::serialize() +myclass::unserialize('Value from serialize()') +object(myclass)#%d (0) { +} + +And now magic PDO using fetchAll(PDO::FETCH_CLASS|PDO::FETCH_SERIALIZE)... +myclass::unserialize('Data fetched from DB to be given to unserialize()') +object(myclass)#%d (0) { +} +myclass::unserialize('Data fetched from DB to be given to unserialize()') +object(myclass)#%d (0) { +} + +And now PDO using setFetchMode(PDO::FETCH:CLASS|PDO::FETCH_SERIALIZE) + fetch()... +myclass::unserialize('Data fetched from DB to be given to unserialize()') +object(myclass)#%d (0) { +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetchobject.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetchobject.php new file mode 100644 index 000000000..8e90457d0 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetchobject.php @@ -0,0 +1,60 @@ +prepare($query); + + class myclass { + + private $set_calls = 0; + protected static $static_set_calls = 0; + + // NOTE: PDO does not care about protected + protected $grp; + + // NOTE: PDO does not care about private and calls __construct() after __set() + private function __construct($param1, $param2) { + printf("myclass::__construct(%s, %s): %d / %d\n", + $param1, $param2, + self::$static_set_calls, $this->set_calls); + } + + // NOTE: PDO will call __set() prior to calling __construct() + public function __set($prop, $value) { + $this->not_a_magic_one(); + printf("myclass::__set(%s, -%s-) %d\n", + $prop, var_export($value, true), $this->set_calls, self::$static_set_calls); + if ("" != $prop) + $this->{$prop} = $value; + } + + // NOTE: PDO can call regular methods prior to calling __construct() + public function not_a_magic_one() { + $this->set_calls++; + self::$static_set_calls++; + } + + } + $stmt->execute(); + $rowno = 0; + $rows[] = array(); + while (is_object($rows[] = $stmt->fetchObject('myclass', array($rowno++, $rowno)))) + ; + + var_dump($rows[$rowno - 1]); + +} catch (PDOException $e) { + // we should never get here, we use warnings, but never trust a system... + printf("[001] %s, [%s} %s\n", + $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo())); +} + +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetchobject.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetchobject.php.expectf new file mode 100644 index 000000000..d3edb53f6 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_fetchobject.php.expectf @@ -0,0 +1,26 @@ +myclass::__set(id, -'1'-) 1 +myclass::__set(, -''-) 2 +myclass::__set(null, -NULL-) 3 +myclass::__set(, -''-) 4 +myclass::__construct(0, 1): 4 / 4 +myclass::__set(id, -'2'-) 1 +myclass::__set(, -''-) 2 +myclass::__set(null, -NULL-) 3 +myclass::__set(, -''-) 4 +myclass::__construct(1, 2): 8 / 4 +myclass::__set(id, -'3'-) 1 +myclass::__set(, -''-) 2 +myclass::__set(null, -NULL-) 3 +myclass::__set(, -''-) 4 +myclass::__construct(2, 3): 12 / 4 +object(myclass)#%d (4) { + [%u|b%"set_calls":"myclass":private]=> + int(4) + [%u|b%"grp":protected]=> + NULL + [%u|b%"id"]=> + %unicode|string%(1) "3" + [%u|b%"null"]=> + NULL +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_getcolumnmeta.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_getcolumnmeta.php new file mode 100644 index 000000000..624ee21b3 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_getcolumnmeta.php @@ -0,0 +1,295 @@ +setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); +MySQLPDOTest::createTestTable($db); + +try { + + $stmt = $db->prepare('SELECT id FROM test ORDER BY id ASC'); + + // execute() has not been called yet + // NOTE: no warning + if (false !== ($tmp = $stmt->getColumnMeta(0))) + printf("[002] Expecting false got %s\n", var_export($tmp, true)); + + $stmt->execute(); + // Warning: PDOStatement::getColumnMeta() expects exactly 1 parameter, 0 given in + if (false !== ($tmp = @$stmt->getColumnMeta())) + printf("[003] Expecting false got %s\n", var_export($tmp, true)); + + // invalid offset + if (false !== ($tmp = @$stmt->getColumnMeta(-1))) + printf("[004] Expecting false got %s\n", var_export($tmp, true)); + + // Warning: PDOStatement::getColumnMeta() expects parameter 1 to be long, array given in + if (false !== ($tmp = @$stmt->getColumnMeta(array()))) + printf("[005] Expecting false got %s\n", var_export($tmp, true)); + + // Warning: PDOStatement::getColumnMeta() expects exactly 1 parameter, 2 given in + if (false !== ($tmp = @$stmt->getColumnMeta(1, 1))) + printf("[006] Expecting false got %s\n", var_export($tmp, true)); + + $emulated = $stmt->getColumnMeta(0); + + printf("Testing native PS...\n"); + $db->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[007] Unable to turn off emulated prepared statements\n"); + + $stmt = $db->prepare('SELECT id FROM test ORDER BY id ASC'); + $stmt->execute(); + $native = $stmt->getColumnMeta(0); + if (count($native) == 0) { + printf("[008] Meta data seems wrong, %s / %s\n", + var_export($native, true), var_export($emulated, true)); + } + + // invalid offset + if (false !== ($tmp = $stmt->getColumnMeta(1))) + printf("[009] Expecting false because of invalid offset got %s\n", var_export($tmp, true)); + + + function test_meta(&$db, $offset, $sql_type, $value, $native_type, $pdo_type) { + + $db->exec('DROP TABLE IF EXISTS test'); + + $sql = sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); + if (!($stmt = @$db->prepare($sql)) || (!@$stmt->execute())) { + // Some engines and/or MySQL server versions might not support the data type + return true; + } + + if (!$db->exec(sprintf("INSERT INTO test(id, label) VALUES (1, '%s')", $value))) { + printf("[%03d] + 1] Insert failed, %d - %s\n", $offset, + $db->errorCode(), var_export($db->errorInfo(), true)); + return false; + } + + $stmt = $db->prepare('SELECT id, label FROM test'); + $stmt->execute(); + $meta = $stmt->getColumnMeta(1); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + + if (empty($meta)) { + printf("[%03d + 2] getColumnMeta() failed, %d - %s\n", $offset, + $stmt->errorCode(), var_export($stmt->errorInfo(), true)); + return false; + } + + $elements = array('flags', 'table', 'name', 'len', 'precision', 'pdo_type'); + foreach ($elements as $k => $element) + if (!isset($meta[$element])) { + printf("[%03d + 3] Element %s missing, %s\n", $offset, + $element, var_export($meta, true)); + return false; + } + + if (($meta['table'] != 'test') || ($meta['name'] != 'label')) { + printf("[%03d + 4] Table or field name is wrong, %s\n", $offset, + var_export($meta, true)); + return false; + } + + if (!is_null($native_type)) { + if (!isset($meta['native_type'])) { + printf("[%03d + 5] Element native_type missing, %s\n", $offset, + var_export($meta, true)); + return false; + } + + if (!is_array($native_type)) + $native_type = array($native_type); + + $found = false; + foreach ($native_type as $k => $type) { + if ($meta['native_type'] == $type) { + $found = true; + break; + } + } + + if (!$found) { + printf("[%03d + 6] Expecting native type %s, %s\n", $offset, + var_export($native_type, true), var_export($meta, true)); + return false; + } + } + + if (!is_null($pdo_type) && ($meta['pdo_type'] != $pdo_type)) { + printf("[%03d + 6] Expecting PDO type %s got %s (%s)\n", $offset, + $pdo_type, var_export($meta, true), var_export($meta['native_type'])); + return false; + } + + return true; + } + + $stmt = $db->prepare('SELECT @@sql_mode AS _mode'); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $real_as_float = (false === stristr($row['_mode'], "REAL_AS_FLOAT")) ? false : true; + + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + $is_mysqlnd = MySQLPDOTest::isPDOMySQLnd(); + test_meta($db, 20, 'BIT(8)', 1, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + test_meta($db, 30, 'TINYINT', -127, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + test_meta($db, 40, 'TINYINT UNSIGNED', 255, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + test_meta($db, 50, 'BOOLEAN', 1, NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + + test_meta($db, 60, 'SMALLINT', -32768, 'SHORT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + test_meta($db, 70, 'SMALLINT UNSIGNED', 65535, 'SHORT', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + + test_meta($db, 80, 'MEDIUMINT', -8388608, 'INT24', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + test_meta($db, 90, 'MEDIUMINT UNSIGNED', 16777215, 'INT24', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + + test_meta($db, 100, 'INT', -2147483648, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + test_meta($db, 110, 'INT UNSIGNED', 4294967295, 'LONG', ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + + test_meta($db, 120, 'BIGINT', -9223372036854775808, 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR); + test_meta($db, 130, 'BIGINT UNSIGNED', 18446744073709551615, 'LONGLONG', ($is_mysqlnd) ? ((PHP_INT_SIZE == 4) ? PDO::PARAM_STR : PDO::PARAM_INT) : PDO::PARAM_STR); + + test_meta($db, 130, 'REAL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); + test_meta($db, 140, 'REAL UNSIGNED', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); + test_meta($db, 150, 'REAL ZEROFILL', -1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); + test_meta($db, 160, 'REAL UNSIGNED ZEROFILL', 1.01, ($real_as_float) ? 'FLOAT' : 'DOUBLE', PDO::PARAM_STR); + + test_meta($db, 170, 'DOUBLE', -1.01, 'DOUBLE', PDO::PARAM_STR); + test_meta($db, 180, 'DOUBLE UNSIGNED', 1.01, 'DOUBLE', PDO::PARAM_STR); + test_meta($db, 190, 'DOUBLE ZEROFILL', -1.01, 'DOUBLE', PDO::PARAM_STR); + test_meta($db, 200, 'DOUBLE UNSIGNED ZEROFILL', 1.01, 'DOUBLE', PDO::PARAM_STR); + + test_meta($db, 210, 'FLOAT', -1.01, 'FLOAT', PDO::PARAM_STR); + test_meta($db, 220, 'FLOAT UNSIGNED', 1.01, 'FLOAT', PDO::PARAM_STR); + test_meta($db, 230, 'FLOAT ZEROFILL', -1.01, 'FLOAT', PDO::PARAM_STR); + test_meta($db, 240, 'FLOAT UNSIGNED ZEROFILL', 1.01, 'FLOAT', PDO::PARAM_STR); + + test_meta($db, 250, 'DECIMAL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + test_meta($db, 260, 'DECIMAL UNSIGNED', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + test_meta($db, 270, 'DECIMAL ZEROFILL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + test_meta($db, 280, 'DECIMAL UNSIGNED ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + + test_meta($db, 290, 'NUMERIC', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + test_meta($db, 300, 'NUMERIC UNSIGNED', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + test_meta($db, 310, 'NUMERIC ZEROFILL', -1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + test_meta($db, 320, 'NUMERIC UNSIGNED ZEROFILL', 1.01, array('DECIMAL', 'NEWDECIMAL'), PDO::PARAM_STR); + + test_meta($db, 330, 'DATE', '2008-04-23', array('DATE', 'NEWDATE'), PDO::PARAM_STR); + test_meta($db, 340, 'TIME', '14:37:00', 'TIME', PDO::PARAM_STR); + test_meta($db, 350, 'TIMESTAMP', time(), 'TIMESTAMP', PDO::PARAM_STR); + test_meta($db, 360, 'DATETIME', '2008-03-23 14:38:00', 'DATETIME', PDO::PARAM_STR); + test_meta($db, 370, 'YEAR', '2008', NULL, ($is_mysqlnd) ? PDO::PARAM_INT : PDO::PARAM_STR); + + test_meta($db, 380, 'CHAR(1)', 'a', 'STRING', PDO::PARAM_STR); + test_meta($db, 390, 'CHAR(10)', '0123456789', 'STRING', PDO::PARAM_STR); + test_meta($db, 400, 'CHAR(255)', str_repeat('z', 255), 'STRING', PDO::PARAM_STR); + test_meta($db, 410, 'VARCHAR(1)', 'a', 'VAR_STRING', PDO::PARAM_STR); + test_meta($db, 420, 'VARCHAR(10)', '0123456789', 'VAR_STRING', PDO::PARAM_STR); + test_meta($db, 430, 'VARCHAR(255)', str_repeat('z', 255), 'VAR_STRING', PDO::PARAM_STR); + + test_meta($db, 440, 'BINARY(1)', str_repeat('a', 1), 'STRING', PDO::PARAM_STR); + test_meta($db, 450, 'BINARY(255)', str_repeat('b', 255), 'STRING', PDO::PARAM_STR); + test_meta($db, 460, 'VARBINARY(1)', str_repeat('a', 1), 'VAR_STRING', PDO::PARAM_STR); + test_meta($db, 470, 'VARBINARY(255)', str_repeat('b', 255), 'VAR_STRING', PDO::PARAM_STR); + + test_meta($db, 480, 'TINYBLOB', str_repeat('b', 255), 'BLOB', PDO::PARAM_STR); + test_meta($db, 490, 'BLOB', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + test_meta($db, 500, 'MEDIUMBLOB', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + test_meta($db, 510, 'LONGBLOB', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + + test_meta($db, 520, 'TINYTEXT', str_repeat('b', 255), 'BLOB', PDO::PARAM_STR); + test_meta($db, 530, 'TINYTEXT BINARY', str_repeat('b', 255), 'BLOB', PDO::PARAM_STR); + + test_meta($db, 560, 'TEXT', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + test_meta($db, 570, 'TEXT BINARY', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + + test_meta($db, 580, 'MEDIUMTEXT', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + test_meta($db, 590, 'MEDIUMTEXT BINARY', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + + test_meta($db, 600, 'LONGTEXT', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + test_meta($db, 610, 'LONGTEXT BINARY', str_repeat('b', 256), 'BLOB', PDO::PARAM_STR); + + test_meta($db, 620, "ENUM('yes', 'no') DEFAULT 'yes'", 'no', NULL, PDO::PARAM_STR); + test_meta($db, 630, "SET('yes', 'no') DEFAULT 'yes'", 'no', NULL, PDO::PARAM_STR); + +/* + | spatial_type +*/ + + // unique key + $db->exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label INT UNIQUE) ENGINE = %s', MySQLPDOTest::getTableEngine()); + if (($stmt = @$db->prepare($sql)) && @$stmt->execute()) { + $db->exec('INSERT INTO test(id, label) VALUES (1, 2)'); + $stmt = $db->query('SELECT id, label FROM test'); + $meta = $stmt->getColumnMeta(1); + if (!isset($meta['flags'])) { + printf("[1000] No flags contained in metadata %s\n", var_export($meta, true)); + } else { + $flags = $meta['flags']; + $found = false; + foreach ($flags as $k => $flag) { + if ($flag == 'unique_key') + $found = true; + } + if (!$found) + printf("[1001] Flags seem wrong %s\n", var_export($meta, true)); + } + } + + // primary key + $db->exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT PRIMARY KEY NOT NULL AUTO_INCREMENT) ENGINE = %s', MySQLPDOTest::getTableEngine()); + if (($stmt = @$db->prepare($sql)) && @$stmt->execute()) { + $db->exec('INSERT INTO test(id) VALUES (1)'); + $stmt = $db->query('SELECT id FROM test'); + $meta = $stmt->getColumnMeta(0); + if (!isset($meta['flags'])) { + printf("[1002] No flags contained in metadata %s\n", var_export($meta, true)); + } else { + $flags = $meta['flags']; + $found = false; + foreach ($flags as $k => $flag) { + if ($flag == 'primary_key') + $found = true; + } + if (!$found) + printf("[1003] Flags seem wrong %s\n", var_export($meta, true)); + } + } + + // multiple key + $db->exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label1 INT, label2 INT, INDEX idx1(label1, label2)) ENGINE = %s', MySQLPDOTest::getTableEngine()); + if (($stmt = @$db->prepare($sql)) && @$stmt->execute()) { + $db->exec('INSERT INTO test(id, label1, label2) VALUES (1, 2, 3)'); + $stmt = $db->query('SELECT id, label1, label2 FROM test'); + $meta = $stmt->getColumnMeta(1); + if (!isset($meta['flags'])) { + printf("[1004] No flags contained in metadata %s\n", var_export($meta, true)); + } else { + $flags = $meta['flags']; + $found = false; + foreach ($flags as $k => $flag) { + if ($flag == 'multiple_key') + $found = true; + } + if (!$found) + printf("[1005] Flags seem wrong %s\n", var_export($meta, true)); + } + } + + $stmt = $db->query('SELECT NULL AS col1'); + $meta = $stmt->getColumnMeta(0); + if ('NULL' !== $meta['native_type']) + printf("[1006] Expecting NULL got %s\n", $meta['native_type']); + +} catch (PDOException $e) { + // we should never get here, we use warnings, but never trust a system... + printf("[001] %s, [%s} %s\n", + $e->getMessage(), $db->errorInfo(), implode(' ', $db->errorInfo())); +} + +$db->exec('DROP TABLE IF EXISTS test'); +print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_getcolumnmeta.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_getcolumnmeta.php.expectf new file mode 100644 index 000000000..47978c865 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_getcolumnmeta.php.expectf @@ -0,0 +1,2 @@ +Testing native PS... +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_multiquery.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_multiquery.php new file mode 100644 index 000000000..69452e97d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_multiquery.php @@ -0,0 +1,47 @@ +query('SELECT label FROM test ORDER BY id ASC LIMIT 1; SELECT label FROM test ORDER BY id ASC LIMIT 1'); + var_dump($stmt->errorInfo()); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + var_dump($stmt->errorInfo()); + + } + + function mysql_stmt_multiquery_proper_usage($db) { + + $stmt = $db->query('SELECT label FROM test ORDER BY id ASC LIMIT 1; SELECT label FROM test ORDER BY id ASC LIMIT 1'); + do { + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + } while ($stmt->nextRowset()); + + } + + try { + + printf("Emulated Prepared Statements...\n"); + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + mysql_stmt_multiquery_wrong_usage($db); + mysql_stmt_multiquery_proper_usage($db); + + printf("Native Prepared Statements...\n"); + $db = MySQLPDOTest::factory(); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + mysql_stmt_multiquery_wrong_usage($db); + mysql_stmt_multiquery_proper_usage($db); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_multiquery.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_multiquery.php.expectf new file mode 100644 index 000000000..e8416c2d7 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_multiquery.php.expectf @@ -0,0 +1,41 @@ +Emulated Prepared Statements... +array(3) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + NULL + [2]=> + NULL +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +array(3) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + NULL + [2]=> + NULL +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +array(1) { + [0]=> + array(1) { + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +Native Prepared Statements... +HipHop Warning: %a +HipHop Fatal error: %a \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_nextrowset.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_nextrowset.php new file mode 100644 index 000000000..2e5e51773 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_nextrowset.php @@ -0,0 +1,89 @@ +setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + + MySQLPDOTest::createTestTable($db); + + $stmt = $db->query('SELECT id FROM test'); + if (false !== ($tmp = $stmt->nextRowSet())) + printf("[002] Expecting false got %s\n", var_export($tmp, true)); + + // TODO: should give a warning, but its PDO, let's ignore the missing warning for now + if (false !== ($tmp = $stmt->nextRowSet(1))) + printf("[003] Expecting false got %s\n", var_export($tmp, true)); + + function test_proc1($db) { + + $stmt = $db->query('SELECT @VERSION as _version'); + $tmp = $stmt->fetch(PDO::FETCH_ASSOC); + assert($tmp['_version'] === NULL); + while ($stmt->fetch()) ; + + $db->exec('DROP PROCEDURE IF EXISTS p'); + $db->exec('CREATE PROCEDURE p(OUT ver_param VARCHAR(25)) BEGIN SELECT VERSION() INTO ver_param; END;'); + $db->exec('CALL p(@VERSION)'); + $stmt = $db->query('SELECT @VERSION as _version'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + var_dump($stmt->nextRowSet()); + + } + + function test_proc2($db) { + + $db->exec('DROP PROCEDURE IF EXISTS p'); + $db->exec('CREATE PROCEDURE p() BEGIN SELECT id FROM test ORDER BY id ASC LIMIT 3; SELECT id, label FROM test WHERE id < 4 ORDER BY id DESC LIMIT 3; END;'); + $stmt = $db->query('CALL p()'); + do { + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + } while ($stmt->nextRowSet()); + var_dump($stmt->nextRowSet()); + + } + + try { + + // Emulated PS + printf("Emulated PS...\n"); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + test_proc1($db); + test_proc2($db); + + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0); + test_proc1($db); + test_proc2($db); + + // Native PS + printf("Native PS...\n"); + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + test_proc1($db); + test_proc2($db); + + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + + test_proc1($db); + test_proc2($db); + + @$db->exec('DROP PROCEDURE IF EXISTS p'); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_nextrowset.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_nextrowset.php.expectf new file mode 100644 index 000000000..a894abf65 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_nextrowset.php.expectf @@ -0,0 +1,199 @@ +Emulated PS... +array(1) { + [0]=> + array(1) { + [%u|b%"_version"]=> + %unicode|string%(%d) "%s" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + } + [1]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + } + [2]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + } +} +array(3) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + [%u|b%"label"]=> + %unicode|string%(1) "c" + } + [1]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(1) "b" + } + [2]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +bool(false) +array(1) { + [0]=> + array(1) { + [%u|b%"_version"]=> + %unicode|string%(%d) "%s" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + } + [1]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + } + [2]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + } +} +array(3) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + [%u|b%"label"]=> + %unicode|string%(1) "c" + } + [1]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(1) "b" + } + [2]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +bool(false) +Native PS... +array(1) { + [0]=> + array(1) { + [%u|b%"_version"]=> + %unicode|string%(%d) "%s" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + } + [1]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + } + [2]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + } +} +array(3) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + [%u|b%"label"]=> + %unicode|string%(1) "c" + } + [1]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(1) "b" + } + [2]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +bool(false) +array(1) { + [0]=> + array(1) { + [%u|b%"_version"]=> + %unicode|string%(%d) "%s" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + } + [1]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + } + [2]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + } +} +array(3) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "3" + [%u|b%"label"]=> + %unicode|string%(1) "c" + } + [1]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + [%u|b%"label"]=> + %unicode|string%(1) "b" + } + [2]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +bool(false) +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_rowcount.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_rowcount.php new file mode 100644 index 000000000..c0bf77c5d --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_rowcount.php @@ -0,0 +1,23 @@ +query('SELECT id FROM test WHERE 1 = 0')->rowCount())) + printf("[002] Expecting 0 got %s", var_export($tmp, true)); + + if (1 !== ($tmp = $db->query('SELECT id FROM test WHERE id = 1')->rowCount())) + printf("[003] Expecting 1 got %s", var_export($tmp, true)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_rowcount.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_rowcount.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_rowcount.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_unbuffered_2050.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_unbuffered_2050.php new file mode 100644 index 000000000..31c5352ae --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_unbuffered_2050.php @@ -0,0 +1,103 @@ +setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, 0); + if (0 != $db->getAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY)) + printf("[004] Unable to turn off emulated prepared statements\n"); + + printf("Buffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); + $stmt = $db->query('SELECT id, label FROM test WHERE id = 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + $stmt = $db->query('SELECT id, label FROM test WHERE id = 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + printf("Unbuffered...\n"); + MySQLPDOTest::createTestTable($db); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false); + $stmt = $db->query('SELECT id, label FROM test WHERE id = 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + /* + NOTE - this will cause an error and it OK + When using unbuffered prepared statements MySQL expects you to + fetch all data from the row before sending new data to the server. + PDO::query() will prepare and execute a statement in one step. + After the execution of PDO::query(), MySQL expects you to fetch + the results from the line before sending new commands. However, + PHP/PDO will send a CLOSE message as part of the PDO::query() call. + + The following happens: + + $stmt = PDO::query() + mysql_stmt_prepare() + mysql_stmt_execute() + + $stmt->fetchAll() + mysql_stmt_fetch() + + And now the right side of the expression will be executed first: + $stmt = PDO::query() + PDO::query() + mysql_stmt_prepare + mysql_stmt_execute + + PHP continues at the left side of the expression: + + $stmt = PDO::query() + + What happens is that $stmt gets overwritten. The reference counter of the + zval representing the current value of $stmt. PDO gets a callback that + it has to free the resources associated with the zval representing the + current value of stmt: + mysql_stmt_close + ---> ERROR + ---> execute() has been send on the line, you are supposed to fetch + ---> you must not try to send a CLOSE after execute() + ---> Error: 2050 (CR_FETCH_CANCELED) + ---> Message: Row retrieval was canceled by mysql_stmt_close() call + ---> MySQL does its best to recover the line and cancels the retrieval + + PHP proceeds and assigns the new statement object/zval obtained from + PDO to $stmt. + + Solutions: + - use mysqlnd + - use prepare() + execute() instead of query() + - as there is no explicit close() in PDO, try unset($stmt) before the new assignment + - fix PDO::query() [not the driver, fix PDO itself] + */ + + $stmt = $db->query('SELECT id, label FROM test WHERE id = 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE id = 1'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $stmt = $db->prepare('SELECT id, label FROM test WHERE id = 1'); + $stmt->execute(); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + unset($stmt); + $stmt = $db->query('SELECT id, label FROM test WHERE id = 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + unset($stmt); + $stmt = $db->query('SELECT id, label FROM test WHERE id = 1'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_unbuffered_2050.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_unbuffered_2050.php.expectf new file mode 100644 index 000000000..aa5b50cc8 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_unbuffered_2050.php.expectf @@ -0,0 +1,64 @@ +Native PS... +Buffered... +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +Unbuffered... +HipHop Warning: %a +array(0) { +} +HipHop Warning: %a +array(0) { +} +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +array(1) { + [0]=> + array(2) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + [%u|b%"label"]=> + %unicode|string%(1) "a" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_variable_columncount.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_variable_columncount.php new file mode 100644 index 000000000..17511462c --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_variable_columncount.php @@ -0,0 +1,101 @@ +fetch(PDO::FETCH_ASSOC); + } while ($stmt->nextRowSet()); + + if (!isset($row['one']) || ($row['one'] != 1)) { + printf("[%03d + 1] Expecting array('one' => 1), got %s\n", $offset, var_export($row, true)); + return false; + } + + if (($columns == 2) && + (!isset($row['two']) || ($row['two'] != 2))) { + printf("[%03d + 2] Expecting array('one' => 1, 'two' => 2), got %s\n", $offset, var_export($row, true)); + return false; + } else if (($columns == 1) && isset($row['two'])) { + printf("[%03d + 3] Expecting one array element got two\n", $offset); + return false; + } + + return true; + } + + try { + + // What will happen if a PS returns a differen number of result set column upon each execution? + // Lets try with a SP accepting parameters... + $db->exec('DROP PROCEDURE IF EXISTS p'); + $db->exec('CREATE PROCEDURE p(IN cols INT) BEGIN IF cols < 2 THEN SELECT cols AS "one"; ELSE SELECT 1 AS "one", cols AS "two"; END IF; END;'); + + // Emulates PS first + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + $stmt = $db->prepare('CALL p(?)'); + + $columns = null; + $stmt->bindParam(1, $columns); + for ($i = 0; $i < 5; $i++) { + $columns = ($i % 2) + 1; + $stmt->execute(); + check_result($i, $stmt, $columns); + } + + if (MySQLPDOTest::isPDOMySQLnd()) { + // Native PS + // Libmysql cannot handle such a stored procedure. You will see leaks with libmysql + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $stmt = $db->prepare('CALL p(?)'); + $stmt->bindParam(1, $columns); + for ($i = 5; $i < 10; $i++) { + $columns = ($i % 2) + 1; + $stmt->execute(); + check_result($i, $stmt, $columns); + } + } + + // And now without parameters... - this gives a different control flow inside PDO + $db->exec('DROP PROCEDURE IF EXISTS p'); + $db->exec('CREATE PROCEDURE p() BEGIN DECLARE cols INT; SELECT @numcols INTO cols; IF cols < 2 THEN SET @numcols = 2; SELECT cols AS "one"; ELSE SET @numcols = 1; SELECT 1 AS "one", cols AS "two"; END IF; END;'); + + // Emulates PS first + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + $db->exec('SET @numcols = 1'); + $stmt = $db->prepare('CALL p()'); + $stmt->execute(); + check_result(11, $stmt, 1); + $stmt->execute(); + check_result(12, $stmt, 2); + $db->exec('SET @numcols = 1'); + $stmt->execute(); + check_result(13, $stmt, 1); + + if (MySQLPDOTest::isPDOMySQLnd()) { + // Native PS + // Libmysql cannot handle such a stored procedure. You will see leaks with libmysql + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->exec('SET @numcols = 1'); + $stmt = $db->prepare('CALL p()'); + $stmt->execute(); + check_result(14, $stmt, 1); + $stmt->execute(); + check_result(15, $stmt, 2); + $db->exec('SET @numcols = 1'); + $stmt->execute(); + check_result(16, $stmt, 1); + } + + } catch (PDOException $e) { + printf("[99] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + print "done!"; +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_variable_columncount.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_variable_columncount.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_stmt_variable_columncount.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_subclass.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_subclass.php new file mode 100644 index 000000000..3d0847c0a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_subclass.php @@ -0,0 +1,69 @@ +protocol(); + return call_user_func_array(array($this, 'parent::__construct'), func_get_args()); + } + + public function exec() { + $this->protocol(); + return call_user_func_array(array($this, 'parent::exec'), func_get_args()); + } + + public function query() { + $this->protocol(); + return call_user_func_array(array($this, 'parent::query'), func_get_args()); + } + + public function __call($method, $args) { + print "__call(".var_export($method,true).", ".var_export($args, true).")\n"; + // $this->protocol(); + } + + private function protocol() { + $stack = debug_backtrace(); + if (!isset($stack[1])) + return; + + printf("%s(", $stack[1]['function']); + $args = ''; + foreach ($stack[1]['args'] as $k => $v) + $args .= sprintf("%s, ", var_export($v, true)); + if ($args != '') + printf("%s", substr($args, 0, -2)); + printf(")\n"); + } + + } + + $db = new MyPDO(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_USER, PDO_MYSQL_TEST_PASS); + $db->exec('DROP TABLE IF EXISTS test'); + $db->exec('CREATE TABLE test(id INT)'); + $db->exec('INSERT INTO test(id) VALUES (1), (2)'); + $stmt = $db->query('SELECT * FROM test ORDER BY id ASC'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + var_dump($stmt->fetch()); + $db->intercept_call(); + + + } catch (PDOException $e) { + printf("[001] %s [%s] %s\n", + $e->getMessage(), $db->errorCode(), implode(' ', $db->errorInfo())); + } + + $db->exec('DROP TABLE IF EXISTS test'); + print "done!\n"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_subclass.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_subclass.php.expectf new file mode 100644 index 000000000..ddcc42485 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_subclass.php.expectf @@ -0,0 +1,22 @@ +__construct('%S', '%S', %s) +exec('DROP TABLE IF EXISTS test') +exec('CREATE TABLE test(id INT)') +exec('INSERT INTO test(id) VALUES (1), (2)') +query('SELECT * FROM test ORDER BY id ASC') +array(2) { + [0]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "1" + } + [1]=> + array(1) { + [%u|b%"id"]=> + %unicode|string%(1) "2" + } +} +bool(false) +__call('intercept_call', array ( +)) +exec('DROP TABLE IF EXISTS test') +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types.php new file mode 100644 index 000000000..275f2a86a --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types.php @@ -0,0 +1,171 @@ +exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); + @$db->exec($sql); + if ($db->errorCode() != 0) { + // not all MySQL Server versions and/or engines might support the type + return true; + } + + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (?, ?)'); + $stmt->bindValue(1, $offset); + $stmt->bindValue(2, $value); + if (!$stmt->execute()) { + printf("[%03d + 1] INSERT failed, %s\n", $offset, var_export($stmt->errorInfo(), true)); + return false; + } + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + $stmt = $db->query('SELECT id, label FROM test'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + + if (!isset($row['id']) || !isset($row['label'])) { + printf("[%03d + 2] Fetched result seems wrong, dumping result: %s\n", $offset, var_export($row, true)); + return false; + } + + if ($row['id'] != $offset) { + printf("[%03d + 3] Expecting %s got %s\n", $offset, $row['id']); + return false; + } + + if (!is_null($pattern)) { + if (!preg_match($pattern, $row['label'])) { + printf("[%03d + 5] Value seems wrong, accepting pattern %s got %s, check manually\n", + $offset, $pattern, var_export($row['label'], true)); + return false; + } + + } else { + + $exp = $value; + if (!is_null($ret_value)) { + // we expect a different return value than our input value + // typically the difference is only the type + $exp = $ret_value; + } + if ($row['label'] !== $exp && !is_null($alternative_type) && gettype($row['label']) != $alternative_type) { + printf("[%03d + 4] %s - input = %s/%s, output = %s/%s (alternative type: %s)\n", $offset, + $sql_type, var_export($exp, true), gettype($exp), + var_export($row['label'], true), gettype($row['label']), + $alternative_type); + return false; + } + + } + + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $stmt = $db->query('SELECT id, label FROM test'); + $row_string = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + if (is_null($pattern) && ($row['label'] != $row_string['label'])) { + printf("%s - STRINGIGY = %s, NATIVE = %s\n", $sql_type, var_export($row_string['label'], true), var_export($row['label'], true)); + return false; + } else if (!is_null($pattern) && !preg_match($pattern, $row_string['label'])) { + printf("%s - STRINGIGY = %s, NATIVE = %s, pattern '%s'\n", $sql_type, var_export($row_string['label'], true), var_export($row['label'], true), $pattern); + return false; + } + + + return true; + } + + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + +/* + test_type($db, 20, 'BIT(8)', 1); +*/ + $is_mysqlnd = MySQLPDOTest::isPDOMySQLnd(); + + test_type($db, 30, 'TINYINT', -127, ($is_mysqlnd) ? -127: '-127'); + test_type($db, 40, 'TINYINT UNSIGNED', 255, ($is_mysqlnd) ? 255 : '255'); + test_type($db, 50, 'BOOLEAN', 1, ($is_mysqlnd) ? 1 : '1'); + + test_type($db, 60, 'SMALLINT', -32768, ($is_mysqlnd) ? -32768 : '-32768'); + test_type($db, 70, 'SMALLINT UNSIGNED', 65535, ($is_mysqlnd) ? 65535 : '65535'); + + test_type($db, 80, 'MEDIUMINT', -8388608, ($is_mysqlnd) ? -8388608 : '-8388608'); + test_type($db, 90, 'MEDIUMINT UNSIGNED', 16777215, ($is_mysqlnd) ? 16777215 : '16777215'); + + test_type($db, 100, 'INT', -2147483648, + ($is_mysqlnd) ? ((PHP_INT_SIZE > 4) ? (int)-2147483648 : (double)-2147483648) : '-2147483648', + NULL, ($is_mysqlnd) ? 'integer' : NULL); + + test_type($db, 110, 'INT UNSIGNED', 4294967295, ($is_mysqlnd) ? ((PHP_INT_SIZE > 4) ? 4294967295 : '4294967295') : '4294967295'); + + // no chance to return int with the current PDO version - we are forced to return strings + test_type($db, 120, 'BIGINT', 1, ($is_mysqlnd) ? 1 : '1'); + // to avoid trouble with numeric ranges, lets pass the numbers as a string + test_type($db, 130, 'BIGINT', '-9223372036854775808', NULL, '/^\-9[\.]*22/'); + test_type($db, 140, 'BIGINT UNSIGNED', '18446744073709551615', NULL, '/^1[\.]*844/'); + + test_type($db, 150, 'REAL', -1.01, ($is_mysqlnd) ? -1.01 : '-1.01'); + test_type($db, 160, 'REAL UNSIGNED', 1.01, ($is_mysqlnd) ? 1.01 : '1.01'); + + test_type($db, 170, 'DOUBLE', -1.01, ($is_mysqlnd) ? -1.01 : '-1.01'); + test_type($db, 180, 'DOUBLE UNSIGNED', 1.01, ($is_mysqlnd) ? 1.01 : '1.01'); + + test_type($db, 210, 'FLOAT', -1.01, NULL, '/^\-1.0\d+/'); + test_type($db, 220, 'FLOAT UNSIGNED', 1.01, NULL, '/^1.0\d+/'); + + test_type($db, 250, 'DECIMAL', -1.01, '-1'); + test_type($db, 260, 'DECIMAL UNSIGNED', 1.01, '1'); + + + test_type($db, 290, 'NUMERIC', -1.01, '-1'); + test_type($db, 300, 'NUMERIC UNSIGNED', 1.01, '1'); + + test_type($db, 330, 'DATE', '2008-04-23'); + test_type($db, 340, 'TIME', '14:37:00'); + test_type($db, 350, 'TIMESTAMP', '2008-05-06 21:09:00'); + test_type($db, 360, 'DATETIME', '2008-03-23 14:38:00'); + test_type($db, 370, 'YEAR', 2008, ($is_mysqlnd) ? 2008 : '2008'); + + test_type($db, 380, 'CHAR(1)', 'a'); + test_type($db, 390, 'CHAR(10)', '0123456789'); + test_type($db, 400, 'CHAR(255)', str_repeat('z', 255)); + test_type($db, 410, 'VARCHAR(1)', 'a'); + test_type($db, 420, 'VARCHAR(10)', '0123456789'); + test_type($db, 430, 'VARCHAR(255)', str_repeat('z', 255)); + + test_type($db, 440, 'BINARY(1)', str_repeat('a', 1)); + test_type($db, 450, 'BINARY(255)', str_repeat('b', 255)); + test_type($db, 460, 'VARBINARY(1)', str_repeat('a', 1)); + test_type($db, 470, 'VARBINARY(255)', str_repeat('b', 255)); + + test_type($db, 480, 'TINYBLOB', str_repeat('b', 255)); + test_type($db, 490, 'BLOB', str_repeat('b', 256)); + test_type($db, 500, 'MEDIUMBLOB', str_repeat('b', 256)); + test_type($db, 510, 'LONGBLOB', str_repeat('b', 256)); + + test_type($db, 520, 'TINYTEXT', str_repeat('b', 255)); + test_type($db, 530, 'TINYTEXT BINARY', str_repeat('b', 255)); + + test_type($db, 560, 'TEXT', str_repeat('b', 256)); + test_type($db, 570, 'TEXT BINARY', str_repeat('b', 256)); + + test_type($db, 580, 'MEDIUMTEXT', str_repeat('b', 256)); + test_type($db, 590, 'MEDIUMTEXT BINARY', str_repeat('b', 256)); + + test_type($db, 600, 'LONGTEXT', str_repeat('b', 256)); + test_type($db, 610, 'LONGTEXT BINARY', str_repeat('b', 256)); + + test_type($db, 620, "ENUM('yes', 'no') DEFAULT 'yes'", 'no'); + test_type($db, 630, "SET('yes', 'no') DEFAULT 'yes'", 'no'); + + test_type($db, 640, 'DECIMAL(3,2)', -1.01, '-1.01'); + + + echo "done!\n"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types_zerofill.php b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types_zerofill.php new file mode 100644 index 000000000..f6962fc66 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types_zerofill.php @@ -0,0 +1,115 @@ +exec('DROP TABLE IF EXISTS test'); + $sql = sprintf('CREATE TABLE test(id INT, label %s) ENGINE=%s', $sql_type, MySQLPDOTest::getTableEngine()); + @$db->exec($sql); + if ($db->errorCode() != 0) { + // not all MySQL Server versions and/or engines might support the type + return true; + } + + $stmt = $db->prepare('INSERT INTO test(id, label) VALUES (?, ?)'); + $stmt->bindValue(1, $offset); + $stmt->bindValue(2, $value); + try { + if (!$stmt->execute()) { + printf("[%03d + 1] INSERT failed, %s\n", $offset, var_export($stmt->errorInfo(), true)); + return false; + } + } catch (PDOException $e) { + // This might be a SQL warning on signed values inserted in unsigned columns + // Zerofill implies unsigned but the test plays with signed = negative values as well! + return true; + } + + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + $stmt = $db->query('SELECT id, label FROM test'); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + if (!isset($row['id']) || !isset($row['label'])) { + printf("[%03d + 2] Fetched result seems wrong, dumping result: %s\n", $offset, var_export($row, true)); + return false; + } + + if ($row['id'] != $offset) { + printf("[%03d + 3] Expecting %s got %s\n", $offset, $row['id']); + return false; + } + + if (!is_null($pattern)) { + + if (!preg_match($pattern, $row['label'])) { + printf("[%03d + 5] Value seems wrong, accepting pattern %s got %s, check manually\n", + $offset, $pattern, var_export($row['label'], true)); + return false; + } + + } else { + + $exp = $value; + if (!is_null($ret_value)) { + // we expect a different return value than our input value + // typically the difference is only the type + $exp = $ret_value; + } + + if ($row['label'] !== $exp) { + printf("[%03d + 4] %s - input = %s/%s, output = %s/%s\n", $offset, + $sql_type, var_export($exp, true), gettype($exp), + var_export($row['label'], true), gettype($row['label'])); + return false; + } + + } + + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $stmt = $db->query('SELECT id, label FROM test'); + $row_string = $stmt->fetch(PDO::FETCH_ASSOC); + $stmt->closeCursor(); + if ($row['label'] != $row_string['label']) { + printf("%s - STRINGIGY = %s, NATIVE = %s\n", $sql_type, var_export($row_string['label'], true), var_export($row['label'], true)); + return false; + } + + return true; + } + + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, false); + + $stmt = $db->prepare('SELECT @@sql_mode AS _mode'); + $stmt->execute(); + $row = $stmt->fetch(PDO::FETCH_ASSOC); + $real_as_float = (false === stristr($row['_mode'], "REAL_AS_FLOAT")) ? false : true; + + test_type($db, 100, 'REAL ZEROFILL', -1.01, NULL, '/^[0]*0$/'); + test_type($db, 110, 'REAL ZEROFILL', 1.01, NULL, ($real_as_float) ? '/^[0]*1\.0.*$/' : '/^[0]*1\.01$/'); + test_type($db, 120, 'REAL UNSIGNED ZEROFILL', 1.01, NULL, ($real_as_float) ? '/^[0]*1\..*$/' : '/^[0]*1\.01$/'); + + test_type($db, 130, 'DOUBLE ZEROFILL', -1.01, NULL, '/^[0]*0$/'); + test_type($db, 140, 'DOUBLE ZEROFILL', 1.01, NULL, '/^[0]*1\.01$/'); + test_type($db, 150, 'DOUBLE UNSIGNED ZEROFILL', 1.01, NULL, '/^[0]*1\.01$/'); + + test_type($db, 160, 'FLOAT ZEROFILL', -1.01, NULL, '/^[0]*0$/'); + test_type($db, 170, 'FLOAT ZEROFILL', 1, NULL, '/^[0]*1$/'); + test_type($db, 180, 'FLOAT UNSIGNED ZEROFILL', -1, NULL, '/^[0]*0$/'); + + test_type($db, 190, 'DECIMAL ZEROFILL', -1.01, NULL, '/^[0]*0$/'); + test_type($db, 200, 'DECIMAL ZEROFILL', 1.01, NULL, '/^[0]*1$/'); + test_type($db, 210, 'DECIMAL UNSIGNED ZEROFILL', 1.01, NULL, '/^[0]*1$/'); + + test_type($db, 220, 'NUMERIC ZEROFILL', -1, NULL, '/^[0]*0$/'); + test_type($db, 230, 'NUMERIC ZEROFILL', 1, NULL, '/^[0]*1$/'); + test_type($db, 240, 'NUMERIC UNSIGNED ZEROFILL', 1.01, NULL, '/^[0]*1$/'); + + echo "done!\n"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types_zerofill.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types_zerofill.php.expectf new file mode 100644 index 000000000..dd55c26f1 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pdo_mysql_types_zerofill.php.expectf @@ -0,0 +1 @@ +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5200.php b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5200.php new file mode 100644 index 000000000..8d0cf92e7 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5200.php @@ -0,0 +1,14 @@ +exec("CREATE TABLE test (bar INT NOT NULL, phase enum('please_select', 'I', 'II', 'IIa', 'IIb', 'III', 'IV'))"); + +foreach ($db->query('DESCRIBE test phase')->fetchAll(PDO::FETCH_ASSOC) as $row) { + print_r($row); +} +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5200.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5200.php.expectf new file mode 100644 index 000000000..00375e02b --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5200.php.expectf @@ -0,0 +1,9 @@ +Array +( + [field] => phase + [type] => enum('please_select','I','II','IIa','IIb','III','IV') + [null] => YES + [key] => + [default] => + [extra] => +) \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5780.php b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5780.php new file mode 100644 index 000000000..b4aa763d8 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5780.php @@ -0,0 +1,23 @@ +exec("CREATE TABLE test (login varchar(32) NOT NULL, data varchar(64) NOT NULL)"); +$db->exec("CREATE TABLE test2 (login varchar(32) NOT NULL, password varchar(64) NOT NULL)"); +$db->exec("INSERT INTO test2 (login, password) VALUES ('testing', 'testing')"); +$db->exec("INSERT INTO test2 (login, password) VALUES ('test2', 'testpw2')"); + +$logstmt = $db->prepare('INSERT INTO test (login, data) VALUES (:var1, :var2)'); +$authstmt = $db->prepare('SELECT * FROM test2 WHERE login = :varlog AND password = :varpass'); +$authstmt->execute(array(':varlog' => 'testing', ':varpass' => 'testing')); +var_dump($authstmt->fetch(PDO::FETCH_NUM)); +@var_dump($logstmt->execute(array(':var1' => 'test1', ':var2' => 'test2'))); +$info = $logstmt->errorInfo(); +unset($info[2]); +var_dump($info); +?>exec('DROP TABLE IF EXISTS test'); +$db->exec('DROP TABLE IF EXISTS test2'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5780.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5780.php.expectf new file mode 100644 index 000000000..0bc90ef90 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5780.php.expectf @@ -0,0 +1,13 @@ +array(2) { + [0]=> + %unicode|string%(7) "testing" + [1]=> + %unicode|string%(7) "testing" +} +bool(true) +array(2) { + [0]=> + %unicode|string%(5) "00000" + [1]=> + NULL +} \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5802.php b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5802.php new file mode 100644 index 000000000..f1021a5ab --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5802.php @@ -0,0 +1,30 @@ +exec('create table test ( bar char(3) NULL )'); +$stmt = $db->prepare('insert into test (bar) values(:bar)') or var_dump($db->errorInfo()); + +$bar = 'foo'; +$stmt->bindParam(':bar', $bar); +$stmt->execute() or var_dump($stmt->errorInfo()); + +$bar = null; +$stmt->bindParam(':bar', $bar); +$stmt->execute() or var_dump($stmt->errorInfo()); + +$bar = 'qaz'; +$stmt->bindParam(':bar', $bar); +$stmt->execute() or var_dump($stmt->errorInfo()); + +$stmt = $db->prepare('select * from test') or var_dump($db->errorInfo()); + +if($stmt) $stmt->execute(); +if($stmt) var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + +print "done!"; +?>exec('DROP TABLE IF EXISTS test'); +?> \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5802.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5802.php.expectf new file mode 100644 index 000000000..e85f47435 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/pecl_bug_5802.php.expectf @@ -0,0 +1,18 @@ +array(3) { + [0]=> + array(1) { + [%u|b%"bar"]=> + %unicode|string%(3) "foo" + } + [1]=> + array(1) { + [%u|b%"bar"]=> + NULL + } + [2]=> + array(1) { + [%u|b%"bar"]=> + %unicode|string%(3) "qaz" + } +} +done! \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/show_tables.php b/hphp/test/zend/bad/ext-pdo_mysql/show_tables.php new file mode 100644 index 000000000..0a5c51639 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/show_tables.php @@ -0,0 +1,5 @@ +query('SHOW TABLES')); \ No newline at end of file diff --git a/hphp/test/zend/bad/ext-pdo_mysql/show_tables.php.expectf b/hphp/test/zend/bad/ext-pdo_mysql/show_tables.php.expectf new file mode 100644 index 000000000..635b700b0 --- /dev/null +++ b/hphp/test/zend/bad/ext-pdo_mysql/show_tables.php.expectf @@ -0,0 +1,4 @@ +PDOStatement Object +( + [queryString] => SHOW TABLES +) \ No newline at end of file diff --git a/hphp/test/zend/good/ext-pdo/pdo_test.inc b/hphp/test/zend/good/ext-pdo/pdo_test.inc new file mode 100644 index 000000000..443c8dd82 --- /dev/null +++ b/hphp/test/zend/good/ext-pdo/pdo_test.inc @@ -0,0 +1,84 @@ +$v) putenv("$n=$v"); +} + +class PDOTest { + // create an instance of the PDO driver, based on + // the current environment + static function factory($classname = 'PDO', $drop_test_tables = true) { + $dsn = getenv('PDOTEST_DSN'); + $user = getenv('PDOTEST_USER'); + $pass = getenv('PDOTEST_PASS'); + $attr = getenv('PDOTEST_ATTR'); + if (is_string($attr) && strlen($attr)) { + $attr = unserialize($attr); + } else { + $attr = null; + } + + if ($user === false) $user = NULL; + if ($pass === false) $pass = NULL; + + $db = new $classname($dsn, $user, $pass, $attr); + + if (!$db) { + die("Could not create PDO object (DSN=$dsn, user=$user)\n"); + } + + // clean up any crufty test tables we might have left behind + // on a previous run + static $test_tables = array( + 'test', + 'test2', + 'classtypes' + ); + if ($drop_test_tables) { + foreach ($test_tables as $table) { + $db->exec("DROP TABLE $table"); + } + } + + $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING); + $db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + return $db; + } + + static function skip() { + try { + $db = PDOTest::factory(); + } catch (PDOException $e) { + die("skip " . $e->getMessage()); + } + } + + static function test_factory($file) { + $config = self::get_config($file); + foreach ($config['ENV'] as $k => $v) { + putenv("$k=$v"); + } + return self::factory(); + } + + static function get_config($file) { + $data = file_get_contents($file); + $data = preg_replace('/^.*--REDIRECTTEST--/s', '', $data); + $config = eval($data); + + return $config; + } +} +?> diff --git a/hphp/test/zend/good/ext-pdo_mysql/bug_37445.php b/hphp/test/zend/good/ext-pdo_mysql/bug_37445.php new file mode 100644 index 000000000..69c02213f --- /dev/null +++ b/hphp/test/zend/good/ext-pdo_mysql/bug_37445.php @@ -0,0 +1,8 @@ +setAttribute(PDO :: ATTR_EMULATE_PREPARES, true); +$stmt = $db->prepare("SELECT 1"); +$stmt->bindParam(':a', 'b'); +?> \ No newline at end of file diff --git a/hphp/test/zend/good/ext-pdo_mysql/bug_37445.php.expectf b/hphp/test/zend/good/ext-pdo_mysql/bug_37445.php.expectf new file mode 100644 index 000000000..3dad4aedf --- /dev/null +++ b/hphp/test/zend/good/ext-pdo_mysql/bug_37445.php.expectf @@ -0,0 +1 @@ +HipHop Fatal error: %a \ No newline at end of file diff --git a/hphp/test/zend/good/ext-pdo_mysql/common.phpt b/hphp/test/zend/good/ext-pdo_mysql/common.phpt new file mode 100644 index 000000000..f55d1f883 --- /dev/null +++ b/hphp/test/zend/good/ext-pdo_mysql/common.phpt @@ -0,0 +1,28 @@ +--TEST-- +MySQL +--SKIPIF-- + +--REDIRECTTEST-- +# magic auto-configuration + +$config = array( + 'TESTS' => __DIR__.'/ext/pdo/tests' +); + +if (false !== getenv('PDO_MYSQL_TEST_DSN')) { + # user set them from their shell + $config['ENV']['PDOTEST_DSN'] = getenv('PDO_MYSQL_TEST_DSN'); + $config['ENV']['PDOTEST_USER'] = getenv('PDO_MYSQL_TEST_USER'); + $config['ENV']['PDOTEST_PASS'] = getenv('PDO_MYSQL_TEST_PASS'); + if (false !== getenv('PDO_MYSQL_TEST_ATTR')) { + $config['ENV']['PDOTEST_ATTR'] = getenv('PDO_MYSQL_TEST_ATTR'); + } +} else { + $config['ENV']['PDOTEST_DSN'] = 'mysql:host=localhost;dbname=test'; + $config['ENV']['PDOTEST_USER'] = 'root'; + $config['ENV']['PDOTEST_PASS'] = ''; +} + +return $config; diff --git a/hphp/test/zend/good/ext-pdo_mysql/config.inc b/hphp/test/zend/good/ext-pdo_mysql/config.inc new file mode 100644 index 000000000..2530442c0 --- /dev/null +++ b/hphp/test/zend/good/ext-pdo_mysql/config.inc @@ -0,0 +1,52 @@ + $v) { + putenv("$k=$v"); +} + +/* MySQL specific settings */ +define('PDO_MYSQL_TEST_ENGINE', (false !== getenv('PDO_MYSQL_TEST_ENGINE')) ? getenv('PDO_MYSQL_TEST_ENGINE') : 'MyISAM'); +define('PDO_MYSQL_TEST_HOST', (false !== getenv('PDO_MYSQL_TEST_HOST')) ? getenv('PDO_MYSQL_TEST_HOST') : 'localhost'); +define('PDO_MYSQL_TEST_PORT', (false !== getenv('PDO_MYSQL_TEST_PORT')) ? getenv('PDO_MYSQL_TEST_PORT') : NULL); +define('PDO_MYSQL_TEST_DB', (false !== getenv('PDO_MYSQL_TEST_DB')) ? getenv('PDO_MYSQL_TEST_DB') : 'test'); +define('PDO_MYSQL_TEST_SOCKET', (false !== getenv('PDO_MYSQL_TEST_SOCKET')) ? getenv('PDO_MYSQL_TEST_SOCKET') : NULL); +define('PDO_MYSQL_TEST_DSN', (false !== getenv('PDO_MYSQL_TEST_DSN')) ? getenv('PDO_MYSQL_TEST_DSN') : $config['ENV']['PDOTEST_DSN']); +define('PDO_MYSQL_TEST_USER', (false !== getenv('PDO_MYSQL_TEST_USER')) ? getenv('PDO_MYSQL_TEST_USER') : $config['ENV']['PDOTEST_USER']); +define('PDO_MYSQL_TEST_PASS', (false !== getenv('PDO_MYSQL_TEST_PASS')) ? getenv('PDO_MYSQL_TEST_PASS') : $config['ENV']['PDOTEST_PASS']); +define('PDO_MYSQL_TEST_CHARSET', (false !== getenv('PDO_MYSQL_TEST_CHARSET')) ? getenv('PDO_MYSQL_TEST_CHARSET') : NULL); + +if (!function_exists('sys_get_temp_dir')) { + function sys_get_temp_dir() { + + if (!empty($_ENV['TMP'])) + return realpath( $_ENV['TMP'] ); + if (!empty($_ENV['TMPDIR'])) + return realpath( $_ENV['TMPDIR'] ); + if (!empty($_ENV['TEMP'])) + return realpath( $_ENV['TEMP'] ); + + $temp_file = tempnam(md5(uniqid(rand(), TRUE)), ''); + if ($temp_file) { + $temp_dir = realpath(dirname($temp_file)); + unlink($temp_file); + return $temp_dir; + } + return FALSE; + } +} +?> \ No newline at end of file diff --git a/hphp/tools/import_zend_test.py b/hphp/tools/import_zend_test.py index 808172814..50796264c 100755 --- a/hphp/tools/import_zend_test.py +++ b/hphp/tools/import_zend_test.py @@ -78,7 +78,6 @@ no_import = ( '/ext/xmlwriter/examples/', # not imported yet, but will be - '/ext/pdo_mysql', '/ext/pdo_sqlite', '/ext/spl', '/ext/standard', @@ -211,6 +210,9 @@ other_files = ( '/ext-openssl/openssl.cnf', '/ext-openssl/private.key', '/ext-openssl/public.key', + '/ext-pdo/pdo_test.inc', + '/ext-pdo_mysql/config.inc', + '/ext-pdo_mysql/common.phpt', '/ext-session/save_handler.inc', '/ext-simplexml/bug24392.xml', '/ext-soap-bugs/bug30928.wsdl', @@ -297,16 +299,21 @@ def mkdir_p(path): pass def walk(filename, source): - dest_filename = os.path.basename(filename).replace('.phpt', '.php') + dest_filename = os.path.basename(filename) source_dir = source.lower().replace('/tests', '').replace('/', '-') cur_dir = os.path.dirname(__file__) dest_subdir = os.path.join(cur_dir, '../test/zend/all', source_dir) mkdir_p(dest_subdir) full_dest_filename = os.path.join(dest_subdir, dest_filename) + + # Exactly mirror zend's directories incase some tests depend on random crap. + # We'll only move things we want into 'good' + shutil.copyfile(filename, full_dest_filename) + + full_dest_filename = full_dest_filename.replace('.phpt', '.php') if not '.phpt' in filename: - shutil.copyfile(filename, full_dest_filename) return print "Importing %s" % filename @@ -432,6 +439,9 @@ def walk(filename, source): test = test.replace("_002.xml", "_004.xml") if 'bug61139.php' in full_dest_filename: test += "\nunlink('someFile');\n?>" + if '/ext-pdo_mysql/' in full_dest_filename: + test = test.replace('/../../../ext/pdo/tests/pdo_test.inc', + '/../ext-pdo/pdo_test.inc') file(full_dest_filename, 'w').write(test)