Bug #41078 With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch() returns short string value.
Submitted: 27 Nov 2008 18:04 Modified: 18 Mar 2009 14:48
Reporter: Masahiro Tomita Email Updates:
Status: Closed Impact on me:
None 
Category:MySQL Server Severity:S3 (Non-critical)
Version:5.0.67/5.1/6.0 OS:Linux (Ubuntu 8.10)
Assigned to: Alexey Kopytov CPU Architecture:Any

[27 Nov 2008 18:04] Masahiro Tomita
Description:
If CURSOR_TYPE_READ_ONLY cursor type is used with UTF-8 charset, mysql_stmt_fetch() returns short string value.

1. mysql_query("set names utf8")
2. mysql_stmt_prepare("select ?")
3. mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE, CURSOR_TYPE_READ_ONLY)
4. mysql_stmt_bind_param("abcdefghijklmn")
5. mysql_stmt_execute()
6. mysql_stmt_fetch() returns "abcd"

If STMT_ATTR_CURSOR_TYPE is CURSOR_TYPE_NO_CURSOR or character set is latin1, mysql_stmt_fetch() returns valid value.

How to repeat:
Run this program.

-------------
#include <mysql/mysql.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
    MYSQL *my;
    MYSQL_STMT *st;
    MYSQL_BIND param;

    my = mysql_init(NULL);
    if (mysql_real_connect(my, "127.0.0.1", "tommy", NULL, "test", 0, NULL, 0) == NULL)
        goto error;
    mysql_query(my, "set names utf8");
    if ((st = mysql_stmt_init(my)) == NULL)
        goto error;
    if (mysql_stmt_prepare(st, "select ?", 8) != 0)
        goto stmt_error;
    unsigned long cursor_type = CURSOR_TYPE_READ_ONLY;
    if (mysql_stmt_attr_set(st, STMT_ATTR_CURSOR_TYPE, &cursor_type) != 0)
        goto stmt_error;
    unsigned long len;
    memset(&param, 0, sizeof(param));
    param.buffer_type = MYSQL_TYPE_STRING;
    param.buffer = "abcdefghijklmn";
    len = strlen(param.buffer);
    param.length = &len;
    if (mysql_stmt_bind_param(st, &param) != 0)
        goto stmt_error;
    if (mysql_stmt_execute(st) != 0)
        goto stmt_error;

    MYSQL_BIND result;
    char str[1024];
    my_bool is_null;
    unsigned long length;
    my_bool error;

    memset(&result, 0, sizeof(result));
    memset(str, 0, sizeof(str));
    result.buffer_type = MYSQL_TYPE_STRING;
    result.buffer = str;
    result.buffer_length = sizeof(str);
    result.is_null = &is_null;
    result.length = &length;
    result.error = &error;
    if (mysql_stmt_bind_result(st, &result) != 0)
        goto stmt_error;
    if (mysql_stmt_store_result(st) != 0)
        goto stmt_error;
    mysql_stmt_fetch(st);
    printf("%ld: %s\n", length, str);
    return 0;

  error:
    perror(mysql_error(my));
    exit(1);

  stmt_error:
    perror(mysql_stmt_error(st));
    exit(1);
}
[3 Dec 2008 12:32] MySQL Verification Team
On 5.0 lastest source server:

miguel@hegel:~/dbs/5.0$ ./bug41078
4: abcd

Changing: unsigned long cursor_type = CURSOR_TYPE_NO_CURSOR; //CURSOR_TYPE_READ_ONLY;

miguel@hegel:~/dbs/5.0$ ./bug41078
14: abcdefghijklmn

I will test 5.1/6.0
[3 Dec 2008 12:48] MySQL Verification Team
Thank you for the bug report. Verified as described on 5.0 source but not on 5.1 and 6.0 which with the same client application aborts with the below error message:

5.1:
bug41078: libmysql.c:4359: setup_one_fetch_function: Assertion `param->buffer_length != 0' failed.
Aborted

6.0:
bug41078: libmysql.c:3980: setup_one_fetch_function: Assertion `param->buffer_length != 0' failed.
Aborted
[19 Feb 2009 8:50] Bugs System
A patch for this bug has been committed. After review, it may
be pushed to the relevant source trees for release in the next
version. You can access the patch from:

  http://lists.mysql.com/commits/66833

2749 Alexey Kopytov	2009-02-19
      Fix for bug #41078: With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch()                          
      returns short string value. 
       
      Multibyte character sets were not taken into account when 
      calculating max_length in Item_param::convert_str_value(). As a 
      result, string parameters of a prepared statement could be 
      truncated later when calculating string length in characters by 
      dividing length in bytes by the charset's mbmaxlen value (e.g. in 
      Field_varstring::store()). 
       
      Fixed by taking charset's mbmaxlen into account when calculating 
      max_length in Item_param::convert_str_value().
      modified:
        sql/item.cc
        tests/mysql_client_test.c
[19 Feb 2009 8:53] Alexander Barkov
http://lists.mysql.com/commits/66833 is Ok to push
[9 Mar 2009 14:12] Bugs System
Pushed into 5.0.79 (revid:joro@sun.com-20090309135922-a0di9ebkxoj4d4wv) (version source revid:alexey.kopytov@sun.com-20090219090211-pp36jrg52674k196) (merge vers: 5.0.79) (pib:6)
[13 Mar 2009 17:01] Paul DuBois
Noted in 5.0.79 changelog.

For prepared statements, multibyte character sets were not taking
into account when calculating max_length for string values and
mysql_stmt_fetch() could return truncated strings.

Setting report to NDI pending push into 5.1.x/6.0.x.
[13 Mar 2009 19:07] Bugs System
Pushed into 5.1.33 (revid:joro@sun.com-20090313111355-7bsi1hgkvrg8pdds) (version source revid:alexey.kopytov@sun.com-20090219090323-7yqkhvdjybxz5o9x) (merge vers: 5.1.33) (pib:6)
[14 Mar 2009 1:38] Paul DuBois
Noted in 5.1.33 changelog.

Setting report to NDI pending push into 6.0.x.
[18 Mar 2009 13:16] Bugs System
Pushed into 6.0.11-alpha (revid:joro@sun.com-20090318122208-1b5kvg6zeb4hxwp9) (version source revid:alexey.kopytov@sun.com-20090219090350-ogxmfc79zvv168nk) (merge vers: 6.0.10-alpha) (pib:6)
[18 Mar 2009 14:48] Paul DuBois
Noted in 6.0.11 changelog.
[9 May 2009 16:45] Bugs System
Pushed into 5.1.34-ndb-6.2.18 (revid:jonas@mysql.com-20090508185236-p9b3as7qyauybefl) (version source revid:jonas@mysql.com-20090508100057-30ote4xggi4nq14v) (merge vers: 5.1.33-ndb-6.2.18) (pib:6)
[9 May 2009 17:42] Bugs System
Pushed into 5.1.34-ndb-6.3.25 (revid:jonas@mysql.com-20090509063138-1u3q3v09wnn2txyt) (version source revid:jonas@mysql.com-20090508175813-s6yele2z3oh6o99z) (merge vers: 5.1.33-ndb-6.3.25) (pib:6)
[9 May 2009 18:40] Bugs System
Pushed into 5.1.34-ndb-7.0.6 (revid:jonas@mysql.com-20090509154927-im9a7g846c6u1hzc) (version source revid:jonas@mysql.com-20090509073226-09bljakh9eppogec) (merge vers: 5.1.33-ndb-7.0.6) (pib:6)