summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Hristov <andrey@php.net>2014-08-06 14:52:12 +0300
committerAndrey Hristov <andrey@php.net>2014-08-06 14:52:12 +0300
commit547451796cbd59c236a08429c93a48f184421bac (patch)
treeec3463e7c2789de7f630e4d5d90b720aff18d4b1
parentbff84d7c18a21c5a3c531684375674fc7ffd3746 (diff)
downloadphp-git-547451796cbd59c236a08429c93a48f184421bac.tar.gz
Fix handling of multi-result sets with PS...used to clean not only
the result set but the whole PS.
-rw-r--r--ext/mysqli/tests/mysqli_stmt_multires.phpt98
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c51
2 files changed, 132 insertions, 17 deletions
diff --git a/ext/mysqli/tests/mysqli_stmt_multires.phpt b/ext/mysqli/tests/mysqli_stmt_multires.phpt
new file mode 100644
index 0000000000..cce9f8d19b
--- /dev/null
+++ b/ext/mysqli/tests/mysqli_stmt_multires.phpt
@@ -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
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 23a0f8a687..bdc46bdb06 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -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;
}
/* }}} */