Skip to content

Commit 89bbaf5

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Fixed bug #80458
2 parents 7adc3e8 + 9dc42b4 commit 89bbaf5

File tree

2 files changed

+195
-10
lines changed

2 files changed

+195
-10
lines changed

ext/pdo_mysql/mysql_statement.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,11 @@ static int pdo_mysql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_da
619619
static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori, zend_long offset) /* {{{ */
620620
{
621621
pdo_mysql_stmt *S = (pdo_mysql_stmt*)stmt->driver_data;
622+
623+
if (!S->result) {
624+
PDO_DBG_RETURN(0);
625+
}
626+
622627
#ifdef PDO_USE_MYSQLND
623628
zend_bool fetched_anything;
624629

@@ -632,6 +637,10 @@ static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori
632637

633638
PDO_DBG_RETURN(1);
634639
}
640+
641+
if (!S->stmt && S->current_data) {
642+
mnd_free(S->current_data);
643+
}
635644
#else
636645
int ret;
637646

@@ -655,16 +664,6 @@ static int pdo_mysql_stmt_fetch(pdo_stmt_t *stmt, enum pdo_fetch_orientation ori
655664
}
656665
#endif /* PDO_USE_MYSQLND */
657666

658-
if (!S->result) {
659-
strcpy(stmt->error_code, "HY000");
660-
PDO_DBG_RETURN(0);
661-
}
662-
#ifdef PDO_USE_MYSQLND
663-
if (!S->stmt && S->current_data) {
664-
mnd_free(S->current_data);
665-
}
666-
#endif /* PDO_USE_MYSQLND */
667-
668667
if ((S->current_data = mysql_fetch_row(S->result)) == NULL) {
669668
if (!S->H->buffered && mysql_errno(S->H->server)) {
670669
pdo_mysql_error_stmt(stmt);

ext/pdo_mysql/tests/bug80458.phpt

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
--TEST--
2+
Bug #80458 PDOStatement::fetchAll() throws for upsert queries
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pdo') || !extension_loaded('pdo_mysql')) die('skip not loaded');
6+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
7+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
8+
MySQLPDOTest::skip();
9+
?>
10+
--FILE--
11+
<?php
12+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
13+
14+
$db = MySQLPDOTest::factory();
15+
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
16+
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
17+
18+
$db->query('DROP TABLE IF EXISTS test');
19+
$db->query('CREATE TABLE test (first int) ENGINE = InnoDB');
20+
$res = $db->query('INSERT INTO test(first) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),(13),(14),(15),(16)');
21+
var_dump($res->fetchAll());
22+
23+
$stmt = $db->prepare('DELETE FROM test WHERE first=1');
24+
$stmt->execute();
25+
var_dump($stmt->fetchAll());
26+
27+
$res = $db->query('DELETE FROM test WHERE first=2');
28+
var_dump($res->fetchAll());
29+
30+
$stmt2 = $db->prepare('DELETE FROM test WHERE first=3');
31+
$stmt2->execute();
32+
foreach($stmt2 as $row){
33+
// expect nothing
34+
}
35+
36+
$stmt3 = $db->prepare('DELETE FROM test WHERE first=4');
37+
$stmt3->execute();
38+
var_dump($stmt3->fetch(PDO::FETCH_ASSOC));
39+
40+
$stmt = $db->prepare('SELECT first FROM test WHERE first=5');
41+
$stmt->execute();
42+
var_dump($stmt->fetchAll());
43+
44+
$db->exec('DROP PROCEDURE IF EXISTS nores');
45+
$db->exec('CREATE PROCEDURE nores() BEGIN DELETE FROM test WHERE first=6; END;');
46+
$stmt4 = $db->prepare('CALL nores()');
47+
$stmt4->execute();
48+
var_dump($stmt4->fetchAll());
49+
$db->exec('DROP PROCEDURE IF EXISTS nores');
50+
51+
$db->exec('DROP PROCEDURE IF EXISTS ret');
52+
$db->exec('CREATE PROCEDURE ret() BEGIN SELECT first FROM test WHERE first=7; END;');
53+
$stmt5 = $db->prepare('CALL ret()');
54+
$stmt5->execute();
55+
var_dump($stmt5->fetchAll());
56+
$stmt5->nextRowset(); // needed to fetch the empty result set of CALL
57+
var_dump($stmt5->fetchAll());
58+
$db->exec('DROP PROCEDURE IF EXISTS ret');
59+
60+
/* With emulated prepares */
61+
print("Emulated prepares\n");
62+
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
63+
64+
$stmt = $db->prepare('DELETE FROM test WHERE first=8');
65+
$stmt->execute();
66+
var_dump($stmt->fetchAll());
67+
68+
$res = $db->query('DELETE FROM test WHERE first=9');
69+
var_dump($res->fetchAll());
70+
71+
$stmt2 = $db->prepare('DELETE FROM test WHERE first=10');
72+
$stmt2->execute();
73+
foreach($stmt2 as $row){
74+
// expect nothing
75+
}
76+
77+
$stmt3 = $db->prepare('DELETE FROM test WHERE first=11');
78+
$stmt3->execute();
79+
var_dump($stmt3->fetch(PDO::FETCH_ASSOC));
80+
81+
$stmt = $db->prepare('SELECT first FROM test WHERE first=12');
82+
$stmt->execute();
83+
var_dump($stmt->fetchAll());
84+
85+
$db->exec('DROP PROCEDURE IF EXISTS nores');
86+
$db->exec('CREATE PROCEDURE nores() BEGIN DELETE FROM test WHERE first=13; END;');
87+
$stmt4 = $db->prepare('CALL nores()');
88+
$stmt4->execute();
89+
var_dump($stmt4->fetchAll());
90+
$db->exec('DROP PROCEDURE IF EXISTS nores');
91+
92+
$db->exec('DROP PROCEDURE IF EXISTS ret');
93+
$db->exec('CREATE PROCEDURE ret() BEGIN SELECT first FROM test WHERE first=14; END;');
94+
$stmt5 = $db->prepare('CALL ret()');
95+
$stmt5->execute();
96+
var_dump($stmt5->fetchAll());
97+
$stmt5->nextRowset(); // needed to fetch the empty result set of CALL
98+
var_dump($stmt5->fetchAll());
99+
$db->exec('DROP PROCEDURE IF EXISTS ret');
100+
101+
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
102+
$db->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
103+
104+
$stmt = $db->prepare('DELETE FROM test WHERE first=15');
105+
$stmt->execute();
106+
var_dump($stmt->fetchAll());
107+
108+
$stmt = $db->prepare('SELECT first FROM test WHERE first=16');
109+
$stmt->execute();
110+
var_dump($stmt->fetchAll());
111+
112+
?>
113+
--CLEAN--
114+
<?php
115+
require __DIR__ . '/mysql_pdo_test.inc';
116+
MySQLPDOTest::dropTestTable();
117+
?>
118+
--EXPECT--
119+
array(0) {
120+
}
121+
array(0) {
122+
}
123+
array(0) {
124+
}
125+
bool(false)
126+
array(1) {
127+
[0]=>
128+
array(2) {
129+
["first"]=>
130+
int(5)
131+
[0]=>
132+
int(5)
133+
}
134+
}
135+
array(0) {
136+
}
137+
array(1) {
138+
[0]=>
139+
array(2) {
140+
["first"]=>
141+
int(7)
142+
[0]=>
143+
int(7)
144+
}
145+
}
146+
array(0) {
147+
}
148+
Emulated prepares
149+
array(0) {
150+
}
151+
array(0) {
152+
}
153+
bool(false)
154+
array(1) {
155+
[0]=>
156+
array(2) {
157+
["first"]=>
158+
string(2) "12"
159+
[0]=>
160+
string(2) "12"
161+
}
162+
}
163+
array(0) {
164+
}
165+
array(1) {
166+
[0]=>
167+
array(2) {
168+
["first"]=>
169+
string(2) "14"
170+
[0]=>
171+
string(2) "14"
172+
}
173+
}
174+
array(0) {
175+
}
176+
array(0) {
177+
}
178+
array(1) {
179+
[0]=>
180+
array(2) {
181+
["first"]=>
182+
int(16)
183+
[0]=>
184+
int(16)
185+
}
186+
}

0 commit comments

Comments
 (0)