Description:
The issue appears only when new client code (libmysql from mysql-trunk) connects to old servers (5.5 or 5.6).
If client code specifies prepared statement's cursor type CURSOR_TYPE_READ_ONLY with mysql_stmt_attr_set() then subsequent call to mysql_stmt_execute() hangs.
If cursor type is not specified then mysql_stmt_execute() works as expected.
How to repeat:
1. Build attached client application with trunk version of libmysql
2. Run application against 5.5 or 5.6 version of server
3. application will hang inside mysql_stmt_execute()
Suggested fix:
Below is the patch which solves this issue. Existing code in mysql_execute() unconditionally clears SERVER_STATUS_CURSOR_EXISTS flag from server_status. This is wrong for 5.5 and 5.6 servers which return this flag but does not specify CLIENT_DEPRECATE_EOF capability (thus old server returns cursor but new client code ignores it). After this patch mysql_execute() will clear SERVER_STATUS_CURSOR_EXISTS flag only when server specifies CLIENT_DEPRECATE_EOF capability.
=== modified file 'libmysql/libmysql.c'
--- libmysql/libmysql.c 2014-10-06 13:25:09 +0000
+++ libmysql/libmysql.c 2014-11-11 14:44:23 +0000
@@ -2047,12 +2047,12 @@
(uchar*) packet, length, 1, stmt) ||
(*mysql->methods->read_query_result)(mysql));
- if (mysql->server_status & SERVER_STATUS_CURSOR_EXISTS)
- mysql->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
-
if (!res && (stmt->flags & CURSOR_TYPE_READ_ONLY) &&
(mysql->server_capabilities & CLIENT_DEPRECATE_EOF))
{
+ if (mysql->server_status & SERVER_STATUS_CURSOR_EXISTS)
+ mysql->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
+
/*
if server responds with a cursor then COM_STMT_EXECUTE response format
will be <Metadata><OK>. Hence read the OK packet to get the server status