diff options
author | Andrey Hristov <andrey@php.net> | 2014-08-06 14:52:12 +0300 |
---|---|---|
committer | Andrey Hristov <andrey@php.net> | 2014-08-06 14:52:12 +0300 |
commit | 547451796cbd59c236a08429c93a48f184421bac (patch) | |
tree | ec3463e7c2789de7f630e4d5d90b720aff18d4b1 | |
parent | bff84d7c18a21c5a3c531684375674fc7ffd3746 (diff) | |
download | php-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.phpt | 98 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_ps.c | 51 |
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; } /* }}} */ |