Skip to content

Commit 2df09b9

Browse files
committed
PDO MySQL: Normalize handling of empty stored procedure result set
MySQL always returns a trailing empty result set for stored procedure calls, which is used to convey status information. The PDO MySQL implementation is presently confused about what to do with it: If mysqlnd is used and native prepared statements are used, this result set is skipped. In all other cases it is not skipped. We also have quite a few XFAILed tests relating to this. This patch normalizes (for PHP-8.0 only) the behavior towards always retaining the empty result set. This is simply how MySQL stored procedures work (some expletives omitted here) and we can't distinguish this "useless" result set from an empty result of a multi query. Multi queries are not a concern for native prepared statements, as PDO does not allow them in that case, but they are a concern for emulated prepared statements. Closes phpGH-6497.
1 parent bfa69d2 commit 2df09b9

6 files changed

+66
-36
lines changed

ext/pdo_mysql/mysql_statement.c

-10
Original file line numberDiff line numberDiff line change
@@ -359,16 +359,6 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
359359
PDO_DBG_RETURN(0);
360360
}
361361

362-
if (!mysqlnd_stmt_more_results(S->stmt)) {
363-
/*
364-
MySQL gives us n + 1 result sets for
365-
CALL proc() and n result sets returned by the proc itself.
366-
Result set n + 1 is about the procedure call itself.
367-
As the PDO emulation does not return it, we skip it as well
368-
*/
369-
PDO_DBG_RETURN(0);
370-
}
371-
372362
/* TODO - this code is stolen from execute() - see above */
373363
if (S->result) {
374364
mysql_free_result(S->result);

ext/pdo_mysql/tests/bug_39858.phpt

+8-2
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ if ($version < 50000)
1818
die(sprintf("skip Need MySQL Server 5.0.0+, found %d.%02d.%02d (%d)\n",
1919
$matches[1], $matches[2], $matches[3], $version));
2020
?>
21-
--XFAIL--
22-
nextRowset() problem with stored proc & emulation mode & mysqlnd
2321
--FILE--
2422
<?php
2523
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
@@ -79,13 +77,17 @@ array(1) {
7977
string(1) "4"
8078
}
8179
}
80+
array(0) {
81+
}
8282
array(1) {
8383
[0]=>
8484
array(1) {
8585
["2 * 2"]=>
8686
string(1) "4"
8787
}
8888
}
89+
array(0) {
90+
}
8991
Native Prepared Statements...
9092
array(1) {
9193
[0]=>
@@ -94,11 +96,15 @@ array(1) {
9496
string(1) "4"
9597
}
9698
}
99+
array(0) {
100+
}
97101
array(1) {
98102
[0]=>
99103
array(1) {
100104
["2 * 2"]=>
101105
string(1) "4"
102106
}
103107
}
108+
array(0) {
109+
}
104110
done!

ext/pdo_mysql/tests/bug_41997.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
--TEST--
22
PDO MySQL Bug #41997 (stored procedure call returning single rowset blocks future queries)
3-
--XFAIL--
4-
nextRowset() problem with stored proc & emulation mode & mysqlnd
53
--SKIPIF--
64
<?php
75
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
@@ -46,6 +44,8 @@ array(1) {
4644
string(1) "1"
4745
}
4846
}
47+
array(0) {
48+
}
4949
array(3) {
5050
[0]=>
5151
string(5) "00000"

ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt

+40-20
Original file line numberDiff line numberDiff line change
@@ -53,31 +53,13 @@ MySQLPDOTest::skip();
5353
// requires MySQL 5+
5454
$stmt = $db->prepare('CALL p()');
5555
$stmt->execute();
56-
$expected = array(
57-
array(
58-
"z" => NULL,
59-
"a" => NULL,
60-
"b" => " ",
61-
"c" => NULL,
62-
"d" => " d",
63-
"e" => " e",
64-
),
65-
);
6656
do {
67-
$tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
68-
if ($tmp != $expected) {
69-
printf("[004] Expecting %s got %s\n",
70-
var_export($expected, true), var_export($tmp, true));
71-
}
57+
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
7258
} while ($stmt->nextRowset());
7359

7460
$stmt->execute();
7561
do {
76-
$tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
77-
if ($tmp != $expected) {
78-
printf("[005] Expecting %s got %s\n",
79-
var_export($expected, true), var_export($tmp, true));
80-
}
62+
var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
8163
} while ($stmt->nextRowset());
8264

8365
}
@@ -124,4 +106,42 @@ array(1) {
124106
string(3) "%se"
125107
}
126108
}
109+
array(1) {
110+
[0]=>
111+
array(6) {
112+
["z"]=>
113+
NULL
114+
["a"]=>
115+
string(0) ""
116+
["b"]=>
117+
string(1) " "
118+
["c"]=>
119+
string(0) ""
120+
["d"]=>
121+
string(2) " d"
122+
["e"]=>
123+
string(2) " e"
124+
}
125+
}
126+
array(0) {
127+
}
128+
array(1) {
129+
[0]=>
130+
array(6) {
131+
["z"]=>
132+
NULL
133+
["a"]=>
134+
string(0) ""
135+
["b"]=>
136+
string(1) " "
137+
["c"]=>
138+
string(0) ""
139+
["d"]=>
140+
string(2) " d"
141+
["e"]=>
142+
string(2) " e"
143+
}
144+
}
145+
array(0) {
146+
}
127147
done!

ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt

+8
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ array(3) {
132132
string(1) "a"
133133
}
134134
}
135+
array(0) {
136+
}
135137
bool(false)
136138
array(3) {
137139
[0]=>
@@ -173,6 +175,8 @@ array(3) {
173175
string(1) "a"
174176
}
175177
}
178+
array(0) {
179+
}
176180
bool(false)
177181

178182
Warning: PDO::query(): SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your %s server version for the right syntax to use near 'INSERT INTO test (id, label) VALUES (99, 'x')' at line 1 in %s on line %d
@@ -219,6 +223,8 @@ array(3) {
219223
string(1) "a"
220224
}
221225
}
226+
array(0) {
227+
}
222228
bool(false)
223229
array(3) {
224230
[0]=>
@@ -260,6 +266,8 @@ array(3) {
260266
string(1) "a"
261267
}
262268
}
269+
array(0) {
270+
}
263271
bool(false)
264272
string(5) "00000"
265273
done!

ext/pdo_mysql/tests/pdo_mysql_stmt_nextrowset.phpt

+8-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
--TEST--
22
MySQL PDOStatement->nextRowSet()
3-
--XFAIL--
4-
nextRowset() problem with stored proc & emulation mode & mysqlnd
53
--SKIPIF--
64
<?php
75
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
@@ -159,6 +157,8 @@ array(3) {
159157
string(1) "a"
160158
}
161159
}
160+
array(0) {
161+
}
162162
bool(false)
163163
array(1) {
164164
[0]=>
@@ -208,6 +208,8 @@ array(3) {
208208
string(1) "a"
209209
}
210210
}
211+
array(0) {
212+
}
211213
bool(false)
212214
Native PS...
213215
array(1) {
@@ -258,6 +260,8 @@ array(3) {
258260
string(1) "a"
259261
}
260262
}
263+
array(0) {
264+
}
261265
bool(false)
262266
array(1) {
263267
[0]=>
@@ -307,5 +311,7 @@ array(3) {
307311
string(1) "a"
308312
}
309313
}
314+
array(0) {
315+
}
310316
bool(false)
311317
done!

0 commit comments

Comments
 (0)