]> granicus.if.org Git - php/commitdiff
Fix handling of multi-result sets with PS...used to clean not only
authorAndrey Hristov <andrey@php.net>
Wed, 6 Aug 2014 11:52:12 +0000 (14:52 +0300)
committerAndrey Hristov <andrey@php.net>
Wed, 6 Aug 2014 11:52:12 +0000 (14:52 +0300)
the result set but the whole PS.

ext/mysqli/tests/mysqli_stmt_multires.phpt [new file with mode: 0644]
ext/mysqlnd/mysqlnd_ps.c

diff --git a/ext/mysqli/tests/mysqli_stmt_multires.phpt b/ext/mysqli/tests/mysqli_stmt_multires.phpt
new file mode 100644 (file)
index 0000000..cce9f8d
--- /dev/null
@@ -0,0 +1,98 @@
+--TEST--
+Multiple result set with PS
+--SKIPIF--
+<?php
+require_once('skipif.inc');
+require_once("connect.inc");
+if (!$IS_MYSQLND) {
+    die("skip mysqlnd only test");
+}
+require_once('skipifconnectfailure.inc');
+?>
+--FILE--
+<?php
+       require_once("connect.inc");
+       require('table.inc');
+
+       $stmt = mysqli_stmt_init($link);
+       if (!$link->query('DROP PROCEDURE IF EXISTS p123')) {
+               printf("[001] [%d] %s\n", $link->error, $link->errno);
+       }
+
+       if (!$link->query("CREATE PROCEDURE p123() BEGIN SELECT id+12, CONCAT_WS('-',label,'ahoi') FROM test ORDER BY id LIMIT 1; SELECT id + 42, CONCAT_WS('---',label, label) FROM test ORDER BY id LIMIT 1; END")) {
+               printf("[002] [%d] %s\n", $link->error, $link->errno);
+       }
+       
+       if (!($stmt = $link->prepare("CALL p123"))) {
+               printf("[003] [%d] %s\n", $stmt->error, $stmt->errno);
+       }
+
+       if (!$stmt->execute()) {
+               printf("[005] [%d] %s\n", $stmt->error, $stmt->errno);
+       }
+
+       $c_id = NULL;
+       $c_label = NULL;
+       if (!$stmt->bind_result($c_id, $c_label)) {
+               printf("[004] [%d] %s\n", $stmt->error, $stmt->errno);
+       }
+       var_dump("pre:",$c_id, $c_label);
+
+       if (!$stmt->fetch()) {
+               printf("[006] [%d] %s\n", $stmt->error, $stmt->errno);
+       }
+
+       var_dump("post:",$c_id, $c_label);
+
+       if ($stmt->fetch()) {
+               printf("[007] Shouldn't have fetched anything\n");
+               var_dump($c_id, $c_label);
+       }
+       if (!$stmt->more_results()) {
+               printf("[008] Expected more results\n");
+       } else {
+               var_dump("next_result:", $stmt->next_result());
+       }
+
+       if (!$stmt->bind_result($c_id, $c_label)) {
+               printf("[004] [%d] %s\n", $stmt->error, $stmt->errno);
+       }
+       var_dump("pre:",$c_id, $c_label);
+
+       if (!$stmt->fetch()) {
+               printf("[009] [%d] %s\n", $stmt->error, $stmt->errno);
+       }
+
+       var_dump("post:",$c_id, $c_label);
+
+       if (!$stmt->more_results()) {
+               printf("[010] Expected more results\n");
+       } else {
+               var_dump("next_result:", $stmt->next_result());
+       }
+
+       if (!$stmt->more_results()) {
+               printf("[010] Expected more results\n");
+       } else {
+               var_dump("next_result:", $stmt->next_result());
+       }
+
+       if ($stmt->more_results()) {
+               printf("[011] No more results expected\n");
+       }
+
+       $stmt->close();
+       $link->close();
+
+
+       echo "done";
+?>
+--CLEAN--
+<?php
+       require_once("connect.inc");
+       if (!$link->query('DROP PROCEDURE IF EXISTS p123')) {
+               printf("[001] [%d] %s\n", $link->error, $link->errno);
+       }
+?>
+--EXPECTF--
+done
index 23a0f8a687910de0e18d95f804a8a3ba781a959b..bdc46bdb0610f40a35f15886e7f3dfe5bab2c714 100644 (file)
@@ -50,6 +50,7 @@ enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES *result, void *param,
 static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt TSRMLS_DC);
 static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no TSRMLS_DC);
 
+static void MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s TSRMLS_DC);
 
 /* {{{ mysqlnd_stmt::store_result */
 static MYSQLND_RES *
@@ -226,7 +227,7 @@ MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s TSRMLS_DC)
        DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
 
        /* Free space for next result */
-       s->m->free_stmt_content(s TSRMLS_CC);
+       MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(s TSRMLS_CC);
        {
                enum_func_status ret = s->m->parse_execute_response(s TSRMLS_CC);
                DBG_RETURN(ret);
@@ -2076,6 +2077,37 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param
 /* }}} */
 
 
+/* {{{ mysqlnd_stmt::free_stmt_result */
+static void
+MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s TSRMLS_DC)
+{
+       MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+       DBG_ENTER("mysqlnd_stmt::free_stmt_result");
+       if (!stmt) {
+               DBG_VOID_RETURN;
+       }
+
+       /*
+         First separate the bound variables, which point to the result set, then
+         destroy the set.
+       */
+       mysqlnd_stmt_separate_result_bind(s TSRMLS_CC);
+       /* Not every statement has a result set attached */
+       if (stmt->result) {
+               stmt->result->m.free_result_internal(stmt->result TSRMLS_CC);
+               stmt->result = NULL;
+       }
+       if (stmt->error_info->error_list) {
+               zend_llist_clean(stmt->error_info->error_list);
+               mnd_pefree(stmt->error_info->error_list, s->persistent);
+               stmt->error_info->error_list = NULL;
+       }
+
+       DBG_VOID_RETURN;
+}
+/* }}} */
+
+
 /* {{{ mysqlnd_stmt::free_stmt_content */
 static void
 MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC)
@@ -2108,22 +2140,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s TSRMLS_DC
                stmt->param_bind = NULL;
        }
 
-       /*
-         First separate the bound variables, which point to the result set, then
-         destroy the set.
-       */
-       mysqlnd_stmt_separate_result_bind(s TSRMLS_CC);
-       /* Not every statement has a result set attached */
-       if (stmt->result) {
-               stmt->result->m.free_result_internal(stmt->result TSRMLS_CC);
-               stmt->result = NULL;
-       }
-       if (stmt->error_info->error_list) {
-               zend_llist_clean(stmt->error_info->error_list);
-               mnd_pefree(stmt->error_info->error_list, s->persistent);
-               stmt->error_info->error_list = NULL;
-       }
-
+       MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(s TSRMLS_CC);
        DBG_VOID_RETURN;
 }
 /* }}} */