Bug #41071 libmysql 6.0 doesn't work with Server < 6.0 (charset problems)
Submitted: 27 Nov 2008 14:31 Modified: 9 Jan 2009 9:09
Reporter: Georg Richter Email Updates:
Status: Patch pending Impact on me:
None 
Category:MySQL Server: C API (client library) Severity:S3 (Non-critical)
Version:6.0 OS:Any
Assigned to: Assigned Account CPU Architecture:Any
Triage: Triaged: D1 (Critical)

[27 Nov 2008 14:31] Georg Richter
Description:
When connecting to a < 6.0 server with utf8 default character set,
libmysql 6.0 sends character_set id=45 which is not known in 5.1 and is
silently converted to latin1:

How to repeat:
#include <mysql.h>
#include <stdio.h>

int main()
{
	MYSQL *mysql;
	MYSQL_RES *res;
	MYSQL_ROW *row;
	MY_CHARSET_INFO *cs;

	mysql = mysql_init(NULL);
	mysql_options(mysql, MYSQL_SET_CHARSET_NAME, "utf8");

	mysql_real_connect(mysql, "localhost", "root", "", "", 0, NULL, 0);

	printf("Server version: %s\nClient version: %s\n",
mysql_get_server_info(mysql),
		mysql_get_client_info());

	mysql_query(mysql, "SHOW VARIABLES LIKE 'character_set_client'");
	res = mysql_store_result(mysql);
	row = mysql_fetch_row(res);
	printf("Client character set is %s\n", row[1]);

	cs = mysql->charset;
	printf("Charset number is %d\n", cs->number);

	mysql_free_result(res);
	mysql_close(mysql);
}

Output with different libmysql and server versions:
georg@linux-afsw:~/work/mysql/mysql-server/mysql-6.0/test> ./test
Server version: 5.1.31
Client version: 6.0.9-alpha
Client character set is latin1
Charset number is 45
georg@linux-afsw:~/work/mysql/mysql-server/mysql-6.0/test> ./test
Server version: 5.1.31
Client version: 5.1.31
Client character set is utf8
Charset number is 33
georg@linux-afsw:~/work/mysql/mysql-server/mysql-6.0/test> ./test
Server version: 6.0.9-alpha-debug
Client version: 6.0.9-alpha
Client character set is utf8
Charset number is 45
georg@linux-afsw:~/work/mysql/mysql-server/mysql-6.0/test> ./test
Server version: 6.0.9-alpha-debug
Client version: 5.1.31
Client character set is utf8mb3
Charset number is 33
[27 Nov 2008 14:36] Georg Richter
Patch for bug #41071 (libmysql)

Attachment: bug41071.patch (text/x-patch), 1.27 KiB.

[3 Dec 2008 15:36] Sergei Golubchik
Georg: first I'd prefer a patch to be in an email, not attached, but anyway:

> === modified file 'libmysql/client.c'
> --- libmysql/client.c	2008-10-26 17:32:37 +0000
> +++ libmysql/client.c	2008-11-27 14:15:29 +0000
> @@ -2256,7 +2256,12 @@
>      /* 4.1 server and 4.1 client has a 32 byte option flag */
>      int4store(buff,client_flag);
>      int4store(buff+4, net->max_packet_size);
> -    buff[8]= (char) mysql->charset->number;
> +    /* Servers < 6.0 don't know characterset number 45 (new utf8), so we need to send
> +       corresponding number 33 instead */
> +    if (mysql->charset->number == 45 && mysql_get_server_version(mysql) < 60000)

1. instead of mysql_get_server_version() you can simply do

   mysql->server_version[0] < '6'

three strtoul's are an overkill here.

2. Don't you think that you need to change mysql->charset to be utf8mb3 ?
Now you're telling the server that your charset is 33, while in fact it's 45.
I don't know if it's safe, better to let server's idea of a client charset
to match the reality.

> +      buff[8] = 33;
> +    else
> +      buff[8]= (char) mysql->charset->number;
>      bzero(buff+9, 32-9);
>      end= buff+32;
>    }
> 
> === modified file 'libmysql/libmysql.c'
> --- libmysql/libmysql.c	2008-10-17 11:03:46 +0000
> +++ libmysql/libmysql.c	2008-11-27 11:51:18 +0000
> @@ -439,7 +439,12 @@
>  
>    if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
>    {
> -    int2store(end, (ushort) mysql->charset->number);
> +    /* Servers < 6.0 don't know characterset number 45 (new utf8), so we need to send
> +       corresponding number 33 instead */
> +    if (mysql->charset->number == 45 && mysql_get_server_version(mysql) < 60000)

same here.

> +      int2store(end, 33);
> +    else
> +      int2store(end, (ushort) mysql->charset->number);
>      end+= 2;
>    }
>  
>
[23 Dec 2008 20:53] 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/62281

2797 Jim Winstead	2008-12-23
      Automatically fall back to 3-byte UTF-8 on pre-6.0 servers when connecting
      (or changing users). (Bug #41071, patch by Georg Richter)
[7 Jul 2009 10:36] Ståle Deraas
This bug is related to WL#1213, which is not part of Azalea. The field "Version " says 6.0, 5.4. It should probably only say 6.0. It should therefore be retagged.