]> granicus.if.org Git - php/commitdiff
Fixed bug #79872 by improving error message
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 10 Dec 2020 10:46:29 +0000 (11:46 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 10 Dec 2020 10:46:29 +0000 (11:46 +0100)
The actual behavior here is correct, but the previous error
message was misleading, as neither fetchAll() nor buffered queries
would help in this situation. Instead it is necessary to consume
all rowsets, which can be done by either unsetting the statement
or calling closeCursor().

NEWS
ext/pdo_mysql/mysql_driver.c
ext/pdo_mysql/tests/bug79872.phpt [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index 5178fb162fa410c562bf131e7b3ca7600ac3e050..0a91136d7636375b94d8235518c70f187c222914 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -51,6 +51,7 @@ PHP                                                                        NEWS
     query error). (Nikita)
   . Fixed bug #76815 (PDOStatement cannot be GCed/closeCursor-ed when a
     PROCEDURE resultset SIGNAL). (Nikita)
+  . Fixed bug #79872 (Can't execute query with pending result sets). (Nikita)
 
 - Phar:
   . Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)
index 764c453438ef4d830de825849e5ae62e967d4b8a..90bc7792d5fed86a8434ac3e4cd0d3c98caafb72 100644 (file)
@@ -73,12 +73,20 @@ int _pdo_mysql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int lin
 
        if (einfo->errcode) {
                if (einfo->errcode == 2014) {
-                       einfo->errmsg = pestrdup(
-                               "Cannot execute queries while other unbuffered queries are active.  "
-                               "Consider using PDOStatement::fetchAll().  Alternatively, if your code "
-                               "is only ever going to run against mysql, you may enable query "
-                               "buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.",
-                               dbh->is_persistent);
+                       if (mysql_more_results(H->server)) {
+                               einfo->errmsg = pestrdup(
+                                       "Cannot execute queries while there are pending result sets. "
+                                       "Consider unsetting the previous PDOStatement or calling "
+                                       "PDOStatement::closeCursor()",
+                                       dbh->is_persistent);
+                       } else {
+                               einfo->errmsg = pestrdup(
+                                       "Cannot execute queries while other unbuffered queries are active.  "
+                                       "Consider using PDOStatement::fetchAll().  Alternatively, if your code "
+                                       "is only ever going to run against mysql, you may enable query "
+                                       "buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.",
+                                       dbh->is_persistent);
+                       }
                } else if (einfo->errcode == 2057) {
                        einfo->errmsg = pestrdup(
                                "A stored procedure returning result sets of different size was called. "
diff --git a/ext/pdo_mysql/tests/bug79872.phpt b/ext/pdo_mysql/tests/bug79872.phpt
new file mode 100644 (file)
index 0000000..0d1ecaf
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+Bug #79872: Can't execute query with pending result sets
+--SKIPIF--
+<?php
+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);
+
+$stmt = $db->prepare('SET @foo = 1; SET @bar = 2;');
+$stmt->execute();
+try {
+    var_dump($db->query('SELECT @foo')->fetchAll());
+} catch (PDOException $e) {
+    echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+SQLSTATE[HY000]: General error: 2014 Cannot execute queries while there are pending result sets. Consider unsetting the previous PDOStatement or calling PDOStatement::closeCursor()