Skip to content

Commit f3d5877

Browse files
committed
Backport fix for bug #70066
Given the number of duplicates this bug report had, it seems worthwhile to fix this on PHP-7.4 as well. Cherry-pick of 106e7e4.
1 parent 44b234a commit f3d5877

File tree

5 files changed

+37
-11
lines changed

5 files changed

+37
-11
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ PHP NEWS
3636
statements). (Nikita)
3737
. Fixed bug #78152 (PDO::exec() - Bad error handling with multiple commands).
3838
(Nikita)
39+
. Fixed bug #70066 (Unexpected "Cannot execute queries while other unbuffered
40+
queries"). (Nikita)
3941

4042
- Phpdbg:
4143
. Fixed bug #76813 (Access violation near NULL on source operand). (cmb)

ext/mysqlnd/mysqlnd_libmysql_compat.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@
8282
#define mysql_stmt_param_count(s) mysqlnd_stmt_param_count((s))
8383
#define mysql_stmt_num_rows(s) mysqlnd_stmt_num_rows((s))
8484
#define mysql_stmt_insert_id(s) mysqlnd_stmt_insert_id((s))
85-
#define mysql_stmt_close(s) mysqlnd_stmt_close((s))
85+
#define mysql_stmt_close(s) mysqlnd_stmt_close((s), 0)
8686
#define mysql_stmt_bind_param(s,b) mysqlnd_stmt_bind_param((s), (b))
8787
#define mysql_stmt_bind_result(s,b) mysqlnd_stmt_bind_result((s), (b))
8888
#define mysql_stmt_errno(s) mysqlnd_stmt_errno((s))

ext/pdo_mysql/mysql_driver.c

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -203,18 +203,17 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
203203
}
204204

205205
if (mysql_stmt_prepare(S->stmt, sql, sql_len)) {
206+
if (nsql) {
207+
efree(nsql);
208+
}
206209
/* TODO: might need to pull statement specific info here? */
207210
/* if the query isn't supported by the protocol, fallback to emulation */
208211
if (mysql_errno(H->server) == 1295) {
209-
if (nsql) {
210-
efree(nsql);
211-
}
212+
mysql_stmt_close(S->stmt);
213+
S->stmt = NULL;
212214
goto fallback;
213215
}
214216
pdo_mysql_error(dbh);
215-
if (nsql) {
216-
efree(nsql);
217-
}
218217
PDO_DBG_RETURN(0);
219218
}
220219
if (nsql) {

ext/pdo_mysql/mysql_statement.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,9 @@
3333
#ifdef PDO_USE_MYSQLND
3434
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_mysqlnd(stmt)
3535
# define pdo_free_bound_result(res) zval_ptr_dtor(res.zv)
36-
# define pdo_mysql_stmt_close(stmt) mysqlnd_stmt_close(stmt, 0)
3736
#else
3837
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_libmysql(stmt)
3938
# define pdo_free_bound_result(res) efree(res.buffer)
40-
# define pdo_mysql_stmt_close(stmt) mysql_stmt_close(stmt)
4139
#endif
4240

4341

@@ -58,7 +56,7 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
5856
S->einfo.errmsg = NULL;
5957
}
6058
if (S->stmt) {
61-
pdo_mysql_stmt_close(S->stmt);
59+
mysql_stmt_close(S->stmt);
6260
S->stmt = NULL;
6361
}
6462

@@ -352,7 +350,7 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
352350
PDO_DBG_INF_FMT("stmt=%p", S->stmt);
353351

354352
#if PDO_USE_MYSQLND
355-
if (!H->emulate_prepare) {
353+
if (S->stmt) {
356354
if (!mysqlnd_stmt_more_results(S->stmt)) {
357355
PDO_DBG_RETURN(0);
358356
}

ext/pdo_mysql/tests/bug70066.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #70066: Unexpected "Cannot execute queries while other unbuffered 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+
13+
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
14+
15+
$pdo = MySQLPDOTest::factory();
16+
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
17+
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
18+
19+
$db = $pdo->query('SELECT DATABASE()')->fetchColumn(0);
20+
// USE is not supported in the prepared statement protocol,
21+
// so this will fall back to emulation.
22+
$pdo->query('USE ' . $db);
23+
24+
?>
25+
===DONE===
26+
--EXPECT--
27+
===DONE===

0 commit comments

Comments
 (0)