]> granicus.if.org Git - php/commitdiff
PDO MySQL: Normalize handling of empty stored procedure result set
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 8 Dec 2020 13:28:18 +0000 (14:28 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 8 Dec 2020 16:01:56 +0000 (17:01 +0100)
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 GH-6497.

ext/pdo_mysql/mysql_statement.c
ext/pdo_mysql/tests/bug_39858.phpt
ext/pdo_mysql/tests/bug_41997.phpt
ext/pdo_mysql/tests/pdo_mysql_attr_oracle_nulls.phpt
ext/pdo_mysql/tests/pdo_mysql_multi_stmt_nextrowset.phpt
ext/pdo_mysql/tests/pdo_mysql_stmt_nextrowset.phpt

index c8a6a218abe65dbae64ce536af8ee8f39ca0fec3..9d544b23c2fa95e786f6d72d447f5e66ebc244e3 100644 (file)
@@ -359,16 +359,6 @@ static int pdo_mysql_stmt_next_rowset(pdo_stmt_t *stmt) /* {{{ */
                        PDO_DBG_RETURN(0);
                }
 
-               if (!mysqlnd_stmt_more_results(S->stmt)) {
-                       /*
-                       MySQL gives us n + 1 result sets for
-                       CALL proc() and n result sets returned by the proc itself.
-                       Result set n + 1 is about the procedure call itself.
-                       As the PDO emulation does not return it, we skip it as well
-                       */
-                       PDO_DBG_RETURN(0);
-               }
-
                /* TODO - this code is stolen from execute() - see above */
                if (S->result) {
                        mysql_free_result(S->result);
index e33415eb675a9acf2f58b6e9ca1d5b51f1cc3227..d421d31a38ab1ee518f66e4f42963bc448340a7a 100644 (file)
@@ -18,8 +18,6 @@ if ($version < 50000)
     die(sprintf("skip Need MySQL Server 5.0.0+, found %d.%02d.%02d (%d)\n",
         $matches[1], $matches[2], $matches[3], $version));
 ?>
---XFAIL--
-nextRowset() problem with stored proc & emulation mode & mysqlnd
 --FILE--
 <?php
 require_once(__DIR__ . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
@@ -79,6 +77,8 @@ array(1) {
     string(1) "4"
   }
 }
+array(0) {
+}
 array(1) {
   [0]=>
   array(1) {
@@ -86,6 +86,8 @@ array(1) {
     string(1) "4"
   }
 }
+array(0) {
+}
 Native Prepared Statements...
 array(1) {
   [0]=>
@@ -94,6 +96,8 @@ array(1) {
     string(1) "4"
   }
 }
+array(0) {
+}
 array(1) {
   [0]=>
   array(1) {
@@ -101,4 +105,6 @@ array(1) {
     string(1) "4"
   }
 }
+array(0) {
+}
 done!
index 7ce2e810d43eee84d329bfd328d9f440e598a50e..769080f86a228541d5d5c755d8c7a1d17d7fc00d 100644 (file)
@@ -1,7 +1,5 @@
 --TEST--
 PDO MySQL Bug #41997 (stored procedure call returning single rowset blocks future queries)
---XFAIL--
-nextRowset() problem with stored proc & emulation mode & mysqlnd
 --SKIPIF--
 <?php
 require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
@@ -46,6 +44,8 @@ array(1) {
     string(1) "1"
   }
 }
+array(0) {
+}
 array(3) {
   [0]=>
   string(5) "00000"
index 6d922a037def86c80266e7064507e955b9bd414a..6e98c85bdf5b41de7d8e5e9a1deef25ee8c1f8d6 100644 (file)
@@ -53,31 +53,13 @@ MySQLPDOTest::skip();
         // requires MySQL 5+
         $stmt = $db->prepare('CALL p()');
         $stmt->execute();
-        $expected = array(
-            array(
-                "z" => NULL,
-                "a" => NULL,
-                "b" => " ",
-                "c" => NULL,
-                "d" => " d",
-                "e" => " e",
-            ),
-        );
         do {
-            $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
-            if ($tmp != $expected) {
-                printf("[004] Expecting %s got %s\n",
-                    var_export($expected, true), var_export($tmp, true));
-            }
+            var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
         } while ($stmt->nextRowset());
 
         $stmt->execute();
         do {
-            $tmp = $stmt->fetchAll(PDO::FETCH_ASSOC);
-            if ($tmp != $expected) {
-                printf("[005] Expecting %s got %s\n",
-                    var_export($expected, true), var_export($tmp, true));
-            }
+            var_dump($stmt->fetchAll(PDO::FETCH_ASSOC));
         } while ($stmt->nextRowset());
 
     }
@@ -124,4 +106,42 @@ array(1) {
     string(3) "%se"
   }
 }
+array(1) {
+  [0]=>
+  array(6) {
+    ["z"]=>
+    NULL
+    ["a"]=>
+    string(0) ""
+    ["b"]=>
+    string(1) " "
+    ["c"]=>
+    string(0) ""
+    ["d"]=>
+    string(2) " d"
+    ["e"]=>
+    string(2) " e"
+  }
+}
+array(0) {
+}
+array(1) {
+  [0]=>
+  array(6) {
+    ["z"]=>
+    NULL
+    ["a"]=>
+    string(0) ""
+    ["b"]=>
+    string(1) " "
+    ["c"]=>
+    string(0) ""
+    ["d"]=>
+    string(2) " d"
+    ["e"]=>
+    string(2) " e"
+  }
+}
+array(0) {
+}
 done!
index e17a233109791741e9ff6c2dfb5482cc7818ef2e..a65fd2eed2ef12ec21a14823e8bd4fa1ff2d560a 100644 (file)
@@ -132,6 +132,8 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 array(3) {
   [0]=>
@@ -173,6 +175,8 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 
 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) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 array(3) {
   [0]=>
@@ -260,6 +266,8 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 string(5) "00000"
 done!
index eac4b9e4d80af5cdf0fd72fe29679a0ee7b02a2d..91a4615a52be0d8c4721107d03fe0e82855a04ba 100644 (file)
@@ -1,7 +1,5 @@
 --TEST--
 MySQL PDOStatement->nextRowSet()
---XFAIL--
-nextRowset() problem with stored proc & emulation mode & mysqlnd
 --SKIPIF--
 <?php
 require_once(__DIR__ . DIRECTORY_SEPARATOR . 'skipif.inc');
@@ -159,6 +157,8 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 array(1) {
   [0]=>
@@ -208,6 +208,8 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 Native PS...
 array(1) {
@@ -258,6 +260,8 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 array(1) {
   [0]=>
@@ -307,5 +311,7 @@ array(3) {
     string(1) "a"
   }
 }
+array(0) {
+}
 bool(false)
 done!