From 40267cdcf8f27f7a189ff57d965fa70feaaa69cd Mon Sep 17 00:00:00 2001 From: Andrey Hristov Date: Wed, 23 Jul 2008 14:06:31 +0000 Subject: [PATCH] Fixed bug#44897 - failed to prepare statement After a PS "CALL()" we have at least one result set. If the SP does also some, then we need to clean the wire more fool-proof. --- ext/mysqli/tests/bug44897.phpt | 70 ++++++++++++++++++++++++++++++++++ ext/mysqlnd/mysqlnd_ps.c | 25 ++++++------ 2 files changed, 84 insertions(+), 11 deletions(-) create mode 100644 ext/mysqli/tests/bug44897.phpt diff --git a/ext/mysqli/tests/bug44897.phpt b/ext/mysqli/tests/bug44897.phpt new file mode 100644 index 0000000000..616e24ec41 --- /dev/null +++ b/ext/mysqli/tests/bug44897.phpt @@ -0,0 +1,70 @@ +--TEST-- +Bug #44879 ( failed to prepare statement) +--SKIPIF-- + +--FILE-- +query('DROP PROCEDURE IF EXISTS p')) + printf("[001] [%d] %s\n", $link->errno, $link->error); + + if (!$link->query('CREATE PROCEDURE p(IN new_id INT, IN new_label CHAR(1)) BEGIN INSERT INTO test(id, label) VALUES (new_id, new_label); SELECT new_label; END;')) + printf("[002] [%d] %s\n", $link->errno, $link->error); + + $new_id = 100; + $new_label = 'z'; + + if (!$stmt = $link->prepare('CALL p(?, ?)')) + printf("[003] [%d] %s\n", $link->errno, $link->error); + + if (!$stmt->bind_param('is', $new_id, $new_label) || !$stmt->execute()) + printf("[004] [%d] %s\n", $stmt->errno, $stmt->error); + + $out_new_label = null; + if (!$stmt->bind_result($out_new_label) || !$stmt->fetch()) + printf("[005] [%d] %s\n", $stmt->errno, $stmt->error); + + if ($out_new_label != $new_label) + printf("[006] IN value and returned value differ. Expecting %s/%s got %s/%s\n", + $new_label, gettype($new_label), $out_new_label, gettype($out_new_label)); + + $stmt->close(); + + $stmt2 = $link->prepare('SELECT label FROM test WHERE id = ?'); + if (!is_object($stmt2)) { + + printf("[007] Failed to create new statement object\n"); + + } else { + + if (!$stmt2->bind_param("i", $new_id) || !$stmt2->execute()) + printf("[008] [%d] %s\n", $stmt2->errno, $stmt2->error); + + $out_new_label = null; + if (!$stmt2->bind_result($out_new_label) || !$stmt2->fetch()) + printf("[009] [%d] %s\n", $stmt2->errno, $stmt2->error); + + if ($out_new_label != $new_label) + printf("[010] IN value and returned value differ. Expecting %s/%s got %s/%s\n", + $new_label, gettype($new_label), $out_new_label, gettype($out_new_label)); + + } + + $link->close(); + + print "done!"; +?> +--EXPECTF-- +done! diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 30154bfe54..05bc1ac997 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -1985,7 +1985,7 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const stmt, zend_ zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */]; enum_mysqlnd_collected_stats stat = STAT_LAST; - DBG_ENTER("mysqlnd_stmt::close"); + DBG_ENTER("mysqlnd_stmt::net_close"); DBG_INF_FMT("stmt=%lu", stmt->stmt_id); SET_EMPTY_ERROR(stmt->error_info); @@ -1996,17 +1996,20 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const stmt, zend_ We have to call the appropriate use_result() or store_result() and clean. */ - if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) { - DBG_INF("fetching result set header"); - stmt->default_rset_handler(stmt TSRMLS_CC); - stmt->state = MYSQLND_STMT_USER_FETCHING; - } + do { + DBG_INF_FMT("stmt->state=%d", stmt->state); + if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) { + DBG_INF("fetching result set header"); + stmt->default_rset_handler(stmt TSRMLS_CC); + stmt->state = MYSQLND_STMT_USER_FETCHING; + } - /* unbuffered set not fetched to the end ? Clean the line */ - if (stmt->result) { - DBG_INF("skipping result"); - stmt->result->m.skip_result(stmt->result TSRMLS_CC); - } + /* unbuffered set not fetched to the end ? Clean the line */ + if (stmt->result) { + DBG_INF("skipping result"); + stmt->result->m.skip_result(stmt->result TSRMLS_CC); + } + } while (mysqlnd_stmt_more_results(stmt) && mysqlnd_stmt_next_result(stmt)); /* After this point we are allowed to free the result set, as we have cleaned the line -- 2.40.0