summaryrefslogtreecommitdiff
path: root/libmysql
diff options
context:
space:
mode:
authorunknown <msvensson@neptunus.(none)>2006-02-10 14:50:29 +0100
committerunknown <msvensson@neptunus.(none)>2006-02-10 14:50:29 +0100
commit101e618f7f46fb0012a4166aea7213730a0b4281 (patch)
tree5e837a488d2d41748e956f76d8fd302a9ff588fa /libmysql
parentdb16cfc578e389cd63770aab9fe7bc1f520b2413 (diff)
downloadmariadb-git-101e618f7f46fb0012a4166aea7213730a0b4281.tar.gz
Bug#14013 mysql_stmt_store_result() bombs if a cursor is open
- Add code to 'mysql_stmt_store_result' to allow it to be called on a prepared statement with open server side cursor. - Add tests to mysql_client_test that uses 'mysql_stmt_store_result' client/mysqltest.c: Enable cursor protocol(remove the ifdef BUG14013_FIXED) When running in cursor mode, the warnings from execute needs to be extracted after mysql_stmt_execute, put them in a dynamic string for later use. Untabify some tabs. libmysql/libmysql.c: Allow 'mysql_stmt_store_result' to be called on a statement with an open server side cursor. Detect that a server side cursor is open and send a "fetch" to ask for all rows to be sent to the client. Read all binary rows as normal store. Check that server said last row was sent after all binary rows has been sent. tests/mysql_client_test.c: Update 'fetch_n' function to take parameter indicating if 'mysql_stmt_store_result' should be used on the statement. Call fetch_n with parameter set to use 'mysql_stmt_store_result'
Diffstat (limited to 'libmysql')
-rw-r--r--libmysql/libmysql.c35
1 files changed, 33 insertions, 2 deletions
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 11ee7284cbf..30eecf809c5 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -4757,12 +4757,39 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
if (!stmt->field_count)
DBUG_RETURN(0);
- if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE ||
- mysql->status != MYSQL_STATUS_GET_RESULT)
+
+ if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
+ {
+ set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
+ DBUG_RETURN(1);
+ }
+
+ if (mysql->status == MYSQL_STATUS_READY &&
+ stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
+ {
+ /*
+ Server side cursor exist, tell server to start sending the rows
+ */
+ NET *net= &mysql->net;
+ char buff[4 /* statement id */ +
+ 4 /* number of rows to fetch */];
+
+ /* Send row request to the server */
+ int4store(buff, stmt->stmt_id);
+ int4store(buff + 4, (int)~0); /* number of rows to fetch */
+ if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
+ NullS, 0, 1))
+ {
+ set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
+ DBUG_RETURN(1);
+ }
+ }
+ else if (mysql->status != MYSQL_STATUS_GET_RESULT)
{
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1);
}
+
if (result->data)
{
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
@@ -4803,6 +4830,10 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
DBUG_RETURN(1);
}
+ /* Assert that if there was a cursor, all rows have been fetched */
+ DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
+ (mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));
+
if (stmt->update_max_length)
{
MYSQL_ROWS *cur= result->data;