diff options
author | Anatol Belski <ab@php.net> | 2014-12-06 21:37:15 +0100 |
---|---|---|
committer | Anatol Belski <ab@php.net> | 2014-12-06 21:37:15 +0100 |
commit | ba35b22bc4a7af791ff2ab7c2ca8e9f4aa6d64df (patch) | |
tree | 92d7a7d9dd424b53e50a194af06ec3cfb514633e /ext/pdo_mysql | |
parent | 88bb9fedc4b5fc750524a7b00be1d46fde2f5929 (diff) | |
parent | aa52fcf179d9e233075e4d213d5708cc5b5e1ae2 (diff) | |
download | php-git-ba35b22bc4a7af791ff2ab7c2ca8e9f4aa6d64df.tar.gz |
Merge remote-tracking branch 'origin/master' into native-tls
* origin/master: (35 commits)
Fixed bug #68398 msooxml matches too many archives
Fix zpp call in apache_getenv()
Drop unnecessary zval containers
fixed test
C89 compat
add include for missing localeconv_r proto
updated NEWS
Fixed bug #65230 setting locale randomly broken
Fix compilation error (ref #68424)
Removed useless handlers
Move checks for references into slow paths of operator functions. Remove duplicate opcode handlers.
Revert unintentional docblock change
Restored zip/oci8 PHP 4 code, add PHP 7 checks
Note macro removal in UPGRADING.INTERNALS
Removed ZEND_ENGINE_2 checks (and ZE1 code, it's been a decade!)
Zend Engine 3
Updated NEWS
Updated NEWS
Updated NEWS
Start adding new attribute to control multi statements
...
Diffstat (limited to 'ext/pdo_mysql')
-rw-r--r-- | ext/pdo_mysql/mysql_driver.c | 13 | ||||
-rw-r--r-- | ext/pdo_mysql/pdo_mysql.c | 2 | ||||
-rw-r--r-- | ext/pdo_mysql/php_pdo_mysql_int.h | 3 | ||||
-rw-r--r-- | ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt | 95 | ||||
-rw-r--r-- | ext/pdo_mysql/tests/pdo_mysql_class_constants.phpt | 1 | ||||
-rw-r--r-- | ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt | 261 |
6 files changed, 369 insertions, 6 deletions
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index 7e4945a7b8..73889af5ea 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -556,15 +556,20 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_ #ifdef CLIENT_MULTI_RESULTS |CLIENT_MULTI_RESULTS #endif -#ifdef CLIENT_MULTI_STATEMENTS - |CLIENT_MULTI_STATEMENTS -#endif ; - #if defined(PDO_USE_MYSQLND) int dbname_len = 0; int password_len = 0; #endif + +#ifdef CLIENT_MULTI_STATEMENTS + if (!driver_options) { + connect_opts |= CLIENT_MULTI_STATEMENTS; + } else if (pdo_attr_lval(driver_options, PDO_MYSQL_ATTR_MULTI_STATEMENTS, 1 TSRMLS_CC)) { + connect_opts |= CLIENT_MULTI_STATEMENTS; + } +#endif + PDO_DBG_ENTER("pdo_mysql_handle_factory"); PDO_DBG_INF_FMT("dbh=%p", dbh); #ifdef CLIENT_MULTI_RESULTS diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c index 82dbdbc83a..0e997b1dc7 100644 --- a/ext/pdo_mysql/pdo_mysql.c +++ b/ext/pdo_mysql/pdo_mysql.c @@ -129,7 +129,7 @@ static PHP_MINIT_FUNCTION(pdo_mysql) #if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_SERVER_PUBLIC_KEY", (zend_long)PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY); #endif - + REGISTER_PDO_CLASS_CONST_LONG("MYSQL_ATTR_MULTI_STATEMENTS", (zend_long)PDO_MYSQL_ATTR_MULTI_STATEMENTS); #ifdef PDO_USE_MYSQLND mysqlnd_reverse_api_register_api(&pdo_mysql_reverse_api TSRMLS_CC); diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h index accac8a25e..9493fda6f8 100644 --- a/ext/pdo_mysql/php_pdo_mysql_int.h +++ b/ext/pdo_mysql/php_pdo_mysql_int.h @@ -175,8 +175,9 @@ enum { PDO_MYSQL_ATTR_SSL_CAPATH, PDO_MYSQL_ATTR_SSL_CIPHER, #if MYSQL_VERSION_ID > 50605 || defined(PDO_USE_MYSQLND) - PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY + PDO_MYSQL_ATTR_SERVER_PUBLIC_KEY, #endif + PDO_MYSQL_ATTR_MULTI_STATEMENTS, }; #endif diff --git a/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt b/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt new file mode 100644 index 0000000000..312deddb81 --- /dev/null +++ b/ext/pdo_mysql/tests/pdo_mysql_attr_multi_statements.phpt @@ -0,0 +1,95 @@ +--TEST-- +PDO::MYSQL_ATTR_MULTI_STATEMENTS +--SKIPIF-- +<?php +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc'); +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); +MySQLPDOTest::skip(); +$db = MySQLPDOTest::factory(); +?> +--INI-- +error_reporting=E_ALL +--FILE-- +<?php + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + + $dsn = MySQLPDOTest::getDSN(); + $user = PDO_MYSQL_TEST_USER; + $pass = PDO_MYSQL_TEST_PASS; + + $table = sprintf("test_%s", md5(mt_rand(0, PHP_INT_MAX))); + $db = new PDO($dsn, $user, $pass); + $db->exec(sprintf('DROP TABLE IF EXISTS %s', $table)); + $create = sprintf('CREATE TABLE %s(id INT)', $table); + $db->exec($create); + $db->exec(sprintf('INSERT INTO %s(id) VALUES (1)', $table)); + $stmt = $db->query(sprintf('SELECT * FROM %s; INSERT INTO %s(id) VALUES (2)', $table, $table)); + $stmt->closeCursor(); + $info = $db->errorInfo(); + var_dump($info[0]); + $stmt = $db->query(sprintf('SELECT id FROM %s', $table)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + // A single query with a trailing delimiter. + $stmt = $db->query('SELECT 1 AS value;'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + // New connection, does not allow multiple statements. + $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => false)); + $stmt = $db->query(sprintf('SELECT * FROM %s; INSERT INTO %s(id) VALUES (3)', $table, $table)); + var_dump($stmt); + $info = $db->errorInfo(); + var_dump($info[0]); + + $stmt = $db->query(sprintf('SELECT id FROM %s', $table)); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + // A single query with a trailing delimiter. + $stmt = $db->query('SELECT 1 AS value;'); + var_dump($stmt->fetchAll(PDO::FETCH_ASSOC)); + + $db->exec(sprintf('DROP TABLE IF EXISTS %s', $table)); + print "done!"; +?> +--EXPECTF-- +string(5) "00000" +array(2) { + [0]=> + array(1) { + ["id"]=> + string(1) "1" + } + [1]=> + array(1) { + ["id"]=> + string(1) "2" + } +} +array(1) { + [0]=> + array(1) { + ["value"]=> + string(1) "1" + } +} +bool(false) +string(5) "42000" +array(2) { + [0]=> + array(1) { + ["id"]=> + string(1) "1" + } + [1]=> + array(1) { + ["id"]=> + string(1) "2" + } +} +array(1) { + [0]=> + array(1) { + ["value"]=> + string(1) "1" + } +} +done! + diff --git a/ext/pdo_mysql/tests/pdo_mysql_class_constants.phpt b/ext/pdo_mysql/tests/pdo_mysql_class_constants.phpt index ee0f12358d..f3d0fa6313 100644 --- a/ext/pdo_mysql/tests/pdo_mysql_class_constants.phpt +++ b/ext/pdo_mysql/tests/pdo_mysql_class_constants.phpt @@ -26,6 +26,7 @@ if (!extension_loaded('mysqli') && !extension_loaded('mysqlnd')) { "MYSQL_ATTR_SSL_CAPATH" => true, "MYSQL_ATTR_SSL_CIPHER" => true, "MYSQL_ATTR_COMPRESS" => true, + "MYSQL_ATTR_MULTI_STATEMENTS" => true, ); if (!MySQLPDOTest::isPDOMySQLnd()) { diff --git a/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt b/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt new file mode 100644 index 0000000000..f327aa4089 --- /dev/null +++ b/ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt @@ -0,0 +1,261 @@ +--TEST-- +MySQL PDOStatement->nextRowSet() with PDO::MYSQL_ATTR_MULTI_STATEMENTS either true or false +--SKIPIF-- +<?php +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc'); +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); +MySQLPDOTest::skip(); +$db = MySQLPDOTest::factory(); +$row = $db->query('SELECT VERSION() as _version')->fetch(PDO::FETCH_ASSOC); +$matches = array(); +if (!preg_match('/^(\d+)\.(\d+)\.(\d+)/ismU', $row['_version'], $matches)) + die(sprintf("skip Cannot determine MySQL Server version\n")); + +$version = $matches[0] * 10000 + $matches[1] * 100 + $matches[2]; +if ($version < 50000) + die(sprintf("skip Need MySQL Server 5.0.0+, found %d.%02d.%02d (%d)\n", + $matches[0], $matches[1], $matches[2], $version)); + +if (!MySQLPDOTest::isPDOMySQLnd()) + die("skip This will not work with libmysql"); +?> +--FILE-- +<?php + require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); + $db = MySQLPDOTest::factory(); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + + MySQLPDOTest::createTestTable($db); + + function test_proc($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 { + + // Using native PS for proc, since emulated fails. + printf("Native PS...\n"); + foreach (array(false, true) as $multi) { + $value = $multi ? 'true' : 'false'; + echo "\nTesting with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to {$value}\n"; + $dsn = MySQLPDOTest::getDSN(); + $user = PDO_MYSQL_TEST_USER; + $pass = PDO_MYSQL_TEST_PASS; + $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => $multi)); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 1); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + test_proc($db); + + $db = new PDO($dsn, $user, $pass, array(PDO::MYSQL_ATTR_MULTI_STATEMENTS => $multi)); + $db->setAttribute(PDO::ATTR_STRINGIFY_FETCHES, true); + $db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, 0); + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0); + + test_proc($db); + + // Switch back to emulated prepares to verify multi statement attribute. + $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1); + // This will fail when $multi is false. + $stmt = $db->query("SELECT * FROM test; INSERT INTO test (id, label) VALUES (99, 'x')"); + if ($stmt !== false) { + $stmt->closeCursor(); + } + $info = $db->errorInfo(); + var_dump($info[0]); + } + @$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!"; +?> +--CLEAN-- +<?php +require dirname(__FILE__) . '/mysql_pdo_test.inc'; +MySQLPDOTest::dropTestTable(); +?> +--EXPECTF-- +Native PS... + +Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to false +array(3) { + [0]=> + array(1) { + ["id"]=> + string(1) "1" + } + [1]=> + array(1) { + ["id"]=> + string(1) "2" + } + [2]=> + array(1) { + ["id"]=> + string(1) "3" + } +} +array(3) { + [0]=> + array(2) { + ["id"]=> + string(1) "3" + ["label"]=> + string(1) "c" + } + [1]=> + array(2) { + ["id"]=> + string(1) "2" + ["label"]=> + string(1) "b" + } + [2]=> + array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(1) "a" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + ["id"]=> + string(1) "1" + } + [1]=> + array(1) { + ["id"]=> + string(1) "2" + } + [2]=> + array(1) { + ["id"]=> + string(1) "3" + } +} +array(3) { + [0]=> + array(2) { + ["id"]=> + string(1) "3" + ["label"]=> + string(1) "c" + } + [1]=> + array(2) { + ["id"]=> + string(1) "2" + ["label"]=> + string(1) "b" + } + [2]=> + array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(1) "a" + } +} +bool(false) +string(5) "42000" + +Testing with PDO::MYSQL_ATTR_MULTI_STATEMENTS set to true +array(3) { + [0]=> + array(1) { + ["id"]=> + string(1) "1" + } + [1]=> + array(1) { + ["id"]=> + string(1) "2" + } + [2]=> + array(1) { + ["id"]=> + string(1) "3" + } +} +array(3) { + [0]=> + array(2) { + ["id"]=> + string(1) "3" + ["label"]=> + string(1) "c" + } + [1]=> + array(2) { + ["id"]=> + string(1) "2" + ["label"]=> + string(1) "b" + } + [2]=> + array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(1) "a" + } +} +bool(false) +array(3) { + [0]=> + array(1) { + ["id"]=> + string(1) "1" + } + [1]=> + array(1) { + ["id"]=> + string(1) "2" + } + [2]=> + array(1) { + ["id"]=> + string(1) "3" + } +} +array(3) { + [0]=> + array(2) { + ["id"]=> + string(1) "3" + ["label"]=> + string(1) "c" + } + [1]=> + array(2) { + ["id"]=> + string(1) "2" + ["label"]=> + string(1) "b" + } + [2]=> + array(2) { + ["id"]=> + string(1) "1" + ["label"]=> + string(1) "a" + } +} +bool(false) +string(5) "00000" +done! |