summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-12-09 17:24:30 +0100
committerNikita Popov <nikita.ppv@gmail.com>2020-12-10 09:58:47 +0100
commitf3d5877845358d011174cf87283b456cee6f7f53 (patch)
tree9160a407ac79b63f2130b5fa6bca51f83a866e1b
parent44b234a9bc589ee6c4afe3e1c386d536f750abe2 (diff)
downloadphp-git-f3d5877845358d011174cf87283b456cee6f7f53.tar.gz
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 106e7e4bca7c0fd975eb219b18e3c34957ba8657.
-rw-r--r--NEWS2
-rw-r--r--ext/mysqlnd/mysqlnd_libmysql_compat.h2
-rw-r--r--ext/pdo_mysql/mysql_driver.c11
-rw-r--r--ext/pdo_mysql/mysql_statement.c6
-rw-r--r--ext/pdo_mysql/tests/bug70066.phpt27
5 files changed, 37 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index d3c5e52139..60310b2692 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,8 @@ PHP NEWS
statements). (Nikita)
. Fixed bug #78152 (PDO::exec() - Bad error handling with multiple commands).
(Nikita)
+ . Fixed bug #70066 (Unexpected "Cannot execute queries while other unbuffered
+ queries"). (Nikita)
- Phpdbg:
. Fixed bug #76813 (Access violation near NULL on source operand). (cmb)
diff --git a/ext/mysqlnd/mysqlnd_libmysql_compat.h b/ext/mysqlnd/mysqlnd_libmysql_compat.h
index 93f7254a7c..e737537f5c 100644
--- a/ext/mysqlnd/mysqlnd_libmysql_compat.h
+++ b/ext/mysqlnd/mysqlnd_libmysql_compat.h
@@ -82,7 +82,7 @@
#define mysql_stmt_param_count(s) mysqlnd_stmt_param_count((s))
#define mysql_stmt_num_rows(s) mysqlnd_stmt_num_rows((s))
#define mysql_stmt_insert_id(s) mysqlnd_stmt_insert_id((s))
-#define mysql_stmt_close(s) mysqlnd_stmt_close((s))
+#define mysql_stmt_close(s) mysqlnd_stmt_close((s), 0)
#define mysql_stmt_bind_param(s,b) mysqlnd_stmt_bind_param((s), (b))
#define mysql_stmt_bind_result(s,b) mysqlnd_stmt_bind_result((s), (b))
#define mysql_stmt_errno(s) mysqlnd_stmt_errno((s))
diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c
index 2d8c4698e7..c5c04adf8a 100644
--- a/ext/pdo_mysql/mysql_driver.c
+++ b/ext/pdo_mysql/mysql_driver.c
@@ -203,18 +203,17 @@ static int mysql_handle_preparer(pdo_dbh_t *dbh, const char *sql, size_t sql_len
}
if (mysql_stmt_prepare(S->stmt, sql, sql_len)) {
+ if (nsql) {
+ efree(nsql);
+ }
/* TODO: might need to pull statement specific info here? */
/* if the query isn't supported by the protocol, fallback to emulation */
if (mysql_errno(H->server) == 1295) {
- if (nsql) {
- efree(nsql);
- }
+ mysql_stmt_close(S->stmt);
+ S->stmt = NULL;
goto fallback;
}
pdo_mysql_error(dbh);
- if (nsql) {
- efree(nsql);
- }
PDO_DBG_RETURN(0);
}
if (nsql) {
diff --git a/ext/pdo_mysql/mysql_statement.c b/ext/pdo_mysql/mysql_statement.c
index b2c37dcfec..beb559f0c1 100644
--- a/ext/pdo_mysql/mysql_statement.c
+++ b/ext/pdo_mysql/mysql_statement.c
@@ -33,11 +33,9 @@
#ifdef PDO_USE_MYSQLND
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_mysqlnd(stmt)
# define pdo_free_bound_result(res) zval_ptr_dtor(res.zv)
-# define pdo_mysql_stmt_close(stmt) mysqlnd_stmt_close(stmt, 0)
#else
# define pdo_mysql_stmt_execute_prepared(stmt) pdo_mysql_stmt_execute_prepared_libmysql(stmt)
# define pdo_free_bound_result(res) efree(res.buffer)
-# define pdo_mysql_stmt_close(stmt) mysql_stmt_close(stmt)
#endif
@@ -58,7 +56,7 @@ static int pdo_mysql_stmt_dtor(pdo_stmt_t *stmt) /* {{{ */
S->einfo.errmsg = NULL;
}
if (S->stmt) {
- pdo_mysql_stmt_close(S->stmt);
+ mysql_stmt_close(S->stmt);
S->stmt = NULL;
}
@@ -352,7 +350,7 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
PDO_DBG_INF_FMT("stmt=%p", S->stmt);
#if PDO_USE_MYSQLND
- if (!H->emulate_prepare) {
+ if (S->stmt) {
if (!mysqlnd_stmt_more_results(S->stmt)) {
PDO_DBG_RETURN(0);
}
diff --git a/ext/pdo_mysql/tests/bug70066.phpt b/ext/pdo_mysql/tests/bug70066.phpt
new file mode 100644
index 0000000000..54660fb3f6
--- /dev/null
+++ b/ext/pdo_mysql/tests/bug70066.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #70066: Unexpected "Cannot execute queries while other unbuffered 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');
+
+$pdo = MySQLPDOTest::factory();
+$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, 0);
+
+$db = $pdo->query('SELECT DATABASE()')->fetchColumn(0);
+// USE is not supported in the prepared statement protocol,
+// so this will fall back to emulation.
+$pdo->query('USE ' . $db);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===