mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
commit
9dc42b4114
3 changed files with 199 additions and 10 deletions
4
NEWS
4
NEWS
|
@ -34,6 +34,10 @@ PHP NEWS
|
|||
. Fixed bug #80368 (OpenSSL extension fails to build against LibreSSL due to
|
||||
lack of OCB support). (Nikita)
|
||||
|
||||
- PDO MySQL:
|
||||
. Fixed bug #80458 (PDOStatement::fetchAll() throws for upsert queries).
|
||||
(Kamil Tekiela)
|
||||
|
||||
- Phar:
|
||||
. Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)
|
||||
. Fixed #75102 (`PharData` says invalid checksum for valid tar). (cmb)
|
||||
|
|
|
@ -619,6 +619,11 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
|
|||
static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset) /* {{{ */
|
||||
{
|
||||
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
|
||||
|
||||
if (!S->result) {
|
||||
PDO_DBG_RETURN(0);
|
||||
}
|
||||
|
||||
#ifdef PDO_USE_MYSQLND
|
||||
zend_bool fetched_anything;
|
||||
|
||||
|
@ -632,6 +637,10 @@ static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori
|
|||
|
||||
PDO_DBG_RETURN(1);
|
||||
}
|
||||
|
||||
if (!S->stmt && S->current_data) {
|
||||
mnd_free(S->current_data);
|
||||
}
|
||||
#else
|
||||
int ret;
|
||||
|
||||
|
@ -655,16 +664,6 @@ static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori
|
|||
}
|
||||
#endif /* PDO_USE_MYSQLND */
|
||||
|
||||
if (!S->result) {
|
||||
strcpy(stmt->error_code, "HY000");
|
||||
PDO_DBG_RETURN(0);
|
||||
}
|
||||
#ifdef PDO_USE_MYSQLND
|
||||
if (!S->stmt && S->current_data) {
|
||||
mnd_free(S->current_data);
|
||||
}
|
||||
#endif /* PDO_USE_MYSQLND */
|
||||
|
||||
if ((S->current_data = mysql_fetch_row(S->result)) == NULL) {
|
||||
if (!S->H->buffered && mysql_errno(S->H->server)) {
|
||||
pdo_mysql_error_stmt(stmt);
|
||||
|
|
186
ext/pdo_mysql/tests/bug80458.phpt
Normal file
186
ext/pdo_mysql/tests/bug80458.phpt
Normal file
|
@ -0,0 +1,186 @@
|
|||
--TEST--
|
||||
Bug #80458 PDOStatement::fetchAll() throws for upsert queries
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) die('skip not loaded');
|
||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
|
||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
|
||||
MySQLPDOTest::skip();
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
|
||||
|
||||
$db = MySQLPDOTest::factory();
|
||||
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
|
||||
$db->query('DROP TABLE IF EXISTS test');
|
||||
$db->query('CREATE TABLE test (first int) ENGINE = InnoDB');
|
||||
$res = $db->query('INSERT INTO test(first) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16)');
|
||||
var_dump($res->fetchAll());
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM test WHERE first=1');
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll());
|
||||
|
||||
$res = $db->query('DELETE FROM test WHERE first=2');
|
||||
var_dump($res->fetchAll());
|
||||
|
||||
$stmt2 = $db->prepare('DELETE FROM test WHERE first=3');
|
||||
$stmt2->execute();
|
||||
foreach($stmt2 as $row){
|
||||
// expect nothing
|
||||
}
|
||||
|
||||
$stmt3 = $db->prepare('DELETE FROM test WHERE first=4');
|
||||
$stmt3->execute();
|
||||
var_dump($stmt3->fetch(PDO::FETCH_ASSOC));
|
||||
|
||||
$stmt = $db->prepare('SELECT first FROM test WHERE first=5');
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll());
|
||||
|
||||
$db->exec('DROP PROCEDURE IF EXISTS nores');
|
||||
$db->exec('CREATE PROCEDURE nores() BEGIN DELETE FROM test WHERE first=6; END;');
|
||||
$stmt4 = $db->prepare('CALL nores()');
|
||||
$stmt4->execute();
|
||||
var_dump($stmt4->fetchAll());
|
||||
$db->exec('DROP PROCEDURE IF EXISTS nores');
|
||||
|
||||
$db->exec('DROP PROCEDURE IF EXISTS ret');
|
||||
$db->exec('CREATE PROCEDURE ret() BEGIN SELECT first FROM test WHERE first=7; END;');
|
||||
$stmt5 = $db->prepare('CALL ret()');
|
||||
$stmt5->execute();
|
||||
var_dump($stmt5->fetchAll());
|
||||
$stmt5->nextRowset(); // needed to fetch the empty result set of CALL
|
||||
var_dump($stmt5->fetchAll());
|
||||
$db->exec('DROP PROCEDURE IF EXISTS ret');
|
||||
|
||||
/* With emulated prepares */
|
||||
print("Emulated prepares\n");
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM test WHERE first=8');
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll());
|
||||
|
||||
$res = $db->query('DELETE FROM test WHERE first=9');
|
||||
var_dump($res->fetchAll());
|
||||
|
||||
$stmt2 = $db->prepare('DELETE FROM test WHERE first=10');
|
||||
$stmt2->execute();
|
||||
foreach($stmt2 as $row){
|
||||
// expect nothing
|
||||
}
|
||||
|
||||
$stmt3 = $db->prepare('DELETE FROM test WHERE first=11');
|
||||
$stmt3->execute();
|
||||
var_dump($stmt3->fetch(PDO::FETCH_ASSOC));
|
||||
|
||||
$stmt = $db->prepare('SELECT first FROM test WHERE first=12');
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll());
|
||||
|
||||
$db->exec('DROP PROCEDURE IF EXISTS nores');
|
||||
$db->exec('CREATE PROCEDURE nores() BEGIN DELETE FROM test WHERE first=13; END;');
|
||||
$stmt4 = $db->prepare('CALL nores()');
|
||||
$stmt4->execute();
|
||||
var_dump($stmt4->fetchAll());
|
||||
$db->exec('DROP PROCEDURE IF EXISTS nores');
|
||||
|
||||
$db->exec('DROP PROCEDURE IF EXISTS ret');
|
||||
$db->exec('CREATE PROCEDURE ret() BEGIN SELECT first FROM test WHERE first=14; END;');
|
||||
$stmt5 = $db->prepare('CALL ret()');
|
||||
$stmt5->execute();
|
||||
var_dump($stmt5->fetchAll());
|
||||
$stmt5->nextRowset(); // needed to fetch the empty result set of CALL
|
||||
var_dump($stmt5->fetchAll());
|
||||
$db->exec('DROP PROCEDURE IF EXISTS ret');
|
||||
|
||||
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
|
||||
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
|
||||
|
||||
$stmt = $db->prepare('DELETE FROM test WHERE first=15');
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll());
|
||||
|
||||
$stmt = $db->prepare('SELECT first FROM test WHERE first=16');
|
||||
$stmt->execute();
|
||||
var_dump($stmt->fetchAll());
|
||||
|
||||
?>
|
||||
--CLEAN--
|
||||
<?php
|
||||
require __DIR__ . '/mysql_pdo_test.inc';
|
||||
MySQLPDOTest::dropTestTable();
|
||||
?>
|
||||
--EXPECT--
|
||||
array(0) {
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
bool(false)
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["first"]=>
|
||||
int(5)
|
||||
[0]=>
|
||||
int(5)
|
||||
}
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["first"]=>
|
||||
int(7)
|
||||
[0]=>
|
||||
int(7)
|
||||
}
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
Emulated prepares
|
||||
array(0) {
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
bool(false)
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["first"]=>
|
||||
string(2) "12"
|
||||
[0]=>
|
||||
string(2) "12"
|
||||
}
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["first"]=>
|
||||
string(2) "14"
|
||||
[0]=>
|
||||
string(2) "14"
|
||||
}
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
array(0) {
|
||||
}
|
||||
array(1) {
|
||||
[0]=>
|
||||
array(2) {
|
||||
["first"]=>
|
||||
int(16)
|
||||
[0]=>
|
||||
int(16)
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue