1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-27 18:02:13 +03:00

Patch for BUG#30472: libmysql doesn't reset charset,

insert_id after succ. mysql_change_user() call.

See also WL 4066.
  
This bug reveals two problems:
  - the problem on the client side which was described originally;
  - the problem in protocol / the server side: connection context
    on client and server should be like after mysql_real_connect()
    and be consistent. The server however just resets character
    set variables to the global defaults.

The fix seems to be as follows:
  - extend the protocol so that the client be able to send
    character set information in COM_CHANGE_USER command;
  - change the server so that it understands client character set
    in the command;
  - change the client:
    - reset character set to the default value (which has been
      read from the configuration);
    - send character set in COM_CHANGE_USER command.
This commit is contained in:
anozdrin/alik@station.
2007-09-28 23:30:54 +04:00
parent e452c06438
commit 8051b7568d
5 changed files with 218 additions and 6 deletions

View File

@ -119,6 +119,8 @@ static void client_disconnect(void);
#define DIE_UNLESS(expr) \
((void) ((expr) ? 0 : (die(__FILE__, __LINE__, #expr), 0)))
#define DIE_IF(expr) \
((void) ((expr) ? (die(__FILE__, __LINE__, #expr), 0) : 0))
#define DIE(expr) \
die(__FILE__, __LINE__, #expr)
@ -177,8 +179,8 @@ if (stmt == 0) \
DIE_UNLESS(stmt == 0);\
}
#define mytest(x) if (!x) {myerror(NULL);DIE_UNLESS(FALSE);}
#define mytest_r(x) if (x) {myerror(NULL);DIE_UNLESS(FALSE);}
#define mytest(x) if (!(x)) {myerror(NULL);DIE_UNLESS(FALSE);}
#define mytest_r(x) if ((x)) {myerror(NULL);DIE_UNLESS(FALSE);}
/* A workaround for Sun Forte 5.6 on Solaris x86 */
@ -16649,6 +16651,175 @@ static void test_bug29306()
DBUG_VOID_RETURN;
}
/*
Bug#30472: libmysql doesn't reset charset, insert_id after succ.
mysql_change_user() call row insertions.
*/
static void bug30472_retrieve_charset_info(MYSQL *con,
char *character_set_name,
char *character_set_client,
char *character_set_results,
char *collation_connection)
{
MYSQL_RES *rs;
MYSQL_ROW row;
/* Get the cached client character set name. */
strcpy(character_set_name, mysql_character_set_name(con));
/* Retrieve server character set information. */
DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'character_set_client'"));
DIE_UNLESS(rs= mysql_store_result(con));
DIE_UNLESS(row= mysql_fetch_row(rs));
strcpy(character_set_client, row[1]);
mysql_free_result(rs);
DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'character_set_results'"));
DIE_UNLESS(rs= mysql_store_result(con));
DIE_UNLESS(row= mysql_fetch_row(rs));
strcpy(character_set_results, row[1]);
mysql_free_result(rs);
DIE_IF(mysql_query(con, "SHOW VARIABLES LIKE 'collation_connection'"));
DIE_UNLESS(rs= mysql_store_result(con));
DIE_UNLESS(row= mysql_fetch_row(rs));
strcpy(collation_connection, row[1]);
mysql_free_result(rs);
}
static void test_bug30472()
{
MYSQL con;
char character_set_name_1[MY_CS_NAME_SIZE];
char character_set_client_1[MY_CS_NAME_SIZE];
char character_set_results_1[MY_CS_NAME_SIZE];
char collation_connnection_1[MY_CS_NAME_SIZE];
char character_set_name_2[MY_CS_NAME_SIZE];
char character_set_client_2[MY_CS_NAME_SIZE];
char character_set_results_2[MY_CS_NAME_SIZE];
char collation_connnection_2[MY_CS_NAME_SIZE];
char character_set_name_3[MY_CS_NAME_SIZE];
char character_set_client_3[MY_CS_NAME_SIZE];
char character_set_results_3[MY_CS_NAME_SIZE];
char collation_connnection_3[MY_CS_NAME_SIZE];
char character_set_name_4[MY_CS_NAME_SIZE];
char character_set_client_4[MY_CS_NAME_SIZE];
char character_set_results_4[MY_CS_NAME_SIZE];
char collation_connnection_4[MY_CS_NAME_SIZE];
/* Create a new connection. */
DIE_UNLESS(mysql_init(&con));
DIE_UNLESS(mysql_real_connect(&con,
opt_host,
opt_user,
opt_password,
opt_db ? opt_db : "test",
opt_port,
opt_unix_socket,
CLIENT_FOUND_ROWS));
/* Retrieve character set information. */
bug30472_retrieve_charset_info(&con,
character_set_name_1,
character_set_client_1,
character_set_results_1,
collation_connnection_1);
/* Switch client character set. */
DIE_IF(mysql_set_character_set(&con, "utf8"));
/* Retrieve character set information. */
bug30472_retrieve_charset_info(&con,
character_set_name_2,
character_set_client_2,
character_set_results_2,
collation_connnection_2);
/*
Check that
1) character set has been switched and
2) new character set is different from the original one.
*/
DIE_UNLESS(strcmp(character_set_name_2, "utf8") == 0);
DIE_UNLESS(strcmp(character_set_client_2, "utf8") == 0);
DIE_UNLESS(strcmp(character_set_results_2, "utf8") == 0);
DIE_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0);
DIE_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0);
DIE_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0);
DIE_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0);
DIE_UNLESS(strcmp(collation_connnection_1, collation_connnection_2) != 0);
/* Call mysql_change_user() with the same username, password, database. */
DIE_IF(mysql_change_user(&con,
opt_user,
opt_password,
opt_db ? opt_db : "test"));
/* Retrieve character set information. */
bug30472_retrieve_charset_info(&con,
character_set_name_3,
character_set_client_3,
character_set_results_3,
collation_connnection_3);
/* Check that character set information has been reset. */
DIE_UNLESS(strcmp(character_set_name_1, character_set_name_3) == 0);
DIE_UNLESS(strcmp(character_set_client_1, character_set_client_3) == 0);
DIE_UNLESS(strcmp(character_set_results_1, character_set_results_3) == 0);
DIE_UNLESS(strcmp(collation_connnection_1, collation_connnection_3) == 0);
/* Change connection-default character set in the client. */
con.options.charset_name= my_strdup("utf8", MYF(MY_FAE));
/*
Call mysql_change_user() in order to check that new connection will
have UTF8 character set on the client and on the server.
*/
DIE_IF(mysql_change_user(&con,
opt_user,
opt_password,
opt_db ? opt_db : "test"));
/* Retrieve character set information. */
bug30472_retrieve_charset_info(&con,
character_set_name_4,
character_set_client_4,
character_set_results_4,
collation_connnection_4);
/* Check that we have UTF8 on the server and on the client. */
DIE_UNLESS(strcmp(character_set_name_4, "utf8") == 0);
DIE_UNLESS(strcmp(character_set_client_4, "utf8") == 0);
DIE_UNLESS(strcmp(character_set_results_4, "utf8") == 0);
DIE_UNLESS(strcmp(collation_connnection_4, "utf8_general_ci") == 0);
/* That's it. Cleanup. */
mysql_close(&con);
}
/*
Read and parse arguments and MySQL options from my.cnf
*/
@ -16943,6 +17114,7 @@ static struct my_tests_st my_tests[]= {
{ "test_bug29692", test_bug29692 },
{ "test_bug29306", test_bug29306 },
{ "test_change_user", test_change_user },
{ "test_bug30472", test_bug30472 },
{ 0, 0 }
};