mirror of
https://github.com/MariaDB/server.git
synced 2025-03-29 18:35:35 +01:00
bug #20318 (ctype_ucs2_def test fails with embedded)
there was two problems about charsets in embedded server 1. mysys/charset.c - defined there default_charset_info variable is modified by both server and client code (particularly when --default-charset option is handled) In embedded server we get two codelines modifying one variable. I created separate default_client_charset_info for client code 2. mysql->charset and mysql->options.charset initialization isn't properly done for embedded server - necessary calls added include/sql_common.h: client charset info default declared libmysqld/lib_sql.cc: thd_init_client_charset calls added libmysqld/libmysqld.c: check_embedded_connection moved to client.c to avoid code duplication sql-common/client.c: charset initialization moved to mysql_init_character_set to be used in embedded server sql/sql_parse.cc: thread client charset initialization moved to thd_init_client_charset to avoid code duplication
This commit is contained in:
parent
b10b25fbb5
commit
8b6c2d312b
5 changed files with 91 additions and 108 deletions
|
@ -22,6 +22,7 @@ extern const char *not_error_sqlstate;
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern CHARSET_INFO *default_client_charset_info;
|
||||
MYSQL_FIELD *unpack_fields(MYSQL_DATA *data,MEM_ROOT *alloc,uint fields,
|
||||
my_bool default_value, uint server_capabilities);
|
||||
void free_rows(MYSQL_DATA *cur);
|
||||
|
|
|
@ -41,6 +41,8 @@ static const char *fake_groups[] = { "server", "embedded", 0 };
|
|||
int check_user(THD *thd, enum enum_server_command command,
|
||||
const char *passwd, uint passwd_len, const char *db,
|
||||
bool check_count);
|
||||
void thd_init_client_charset(THD *thd, uint cs_number);
|
||||
|
||||
C_MODE_START
|
||||
#include <mysql.h>
|
||||
#undef ER
|
||||
|
@ -532,10 +534,13 @@ err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
#ifdef NO_EMBEDDED_ACCESS_CHECKS
|
||||
int check_embedded_connection(MYSQL *mysql)
|
||||
{
|
||||
THD *thd= (THD*)mysql->thd;
|
||||
thd_init_client_charset(thd, mysql->charset->number);
|
||||
thd->update_charset();
|
||||
thd->host= (char*)my_localhost;
|
||||
thd->host_or_ip= thd->host;
|
||||
thd->user= my_strdup(mysql->user, MYF(0));
|
||||
|
@ -551,6 +556,8 @@ int check_embedded_connection(MYSQL *mysql)
|
|||
char scramble_buff[SCRAMBLE_LENGTH];
|
||||
int passwd_len;
|
||||
|
||||
thd_init_client_charset(thd, mysql->charset->number);
|
||||
thd->update_charset();
|
||||
if (mysql->options.client_ip)
|
||||
{
|
||||
thd->host= my_strdup(mysql->options.client_ip, MYF(0));
|
||||
|
|
|
@ -85,49 +85,7 @@ static void end_server(MYSQL *mysql)
|
|||
}
|
||||
|
||||
|
||||
static int mysql_init_charset(MYSQL *mysql)
|
||||
{
|
||||
char charset_name_buff[16], *charset_name;
|
||||
|
||||
if ((charset_name=mysql->options.charset_name))
|
||||
{
|
||||
const char *save=charsets_dir;
|
||||
if (mysql->options.charset_dir)
|
||||
charsets_dir=mysql->options.charset_dir;
|
||||
mysql->charset=get_charset_by_name(mysql->options.charset_name,
|
||||
MYF(MY_WME));
|
||||
charsets_dir=save;
|
||||
}
|
||||
else if (mysql->server_language)
|
||||
{
|
||||
charset_name=charset_name_buff;
|
||||
sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */
|
||||
mysql->charset=get_charset((uint8) mysql->server_language, MYF(MY_WME));
|
||||
}
|
||||
else
|
||||
mysql->charset=default_charset_info;
|
||||
|
||||
if (!mysql->charset)
|
||||
{
|
||||
mysql->net.last_errno=CR_CANT_READ_CHARSET;
|
||||
strmov(mysql->net.sqlstate, "HY0000");
|
||||
if (mysql->options.charset_dir)
|
||||
sprintf(mysql->net.last_error,ER(mysql->net.last_errno),
|
||||
charset_name ? charset_name : "unknown",
|
||||
mysql->options.charset_dir);
|
||||
else
|
||||
{
|
||||
char cs_dir_name[FN_REFLEN];
|
||||
get_charsets_dir(cs_dir_name);
|
||||
sprintf(mysql->net.last_error,ER(mysql->net.last_errno),
|
||||
charset_name ? charset_name : "unknown",
|
||||
cs_dir_name);
|
||||
}
|
||||
return mysql->net.last_errno;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mysql_init_character_set(MYSQL *mysql);
|
||||
|
||||
MYSQL * STDCALL
|
||||
mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
|
@ -203,10 +161,10 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||
|
||||
init_embedded_mysql(mysql, client_flag, db_name);
|
||||
|
||||
if (check_embedded_connection(mysql))
|
||||
if (mysql_init_character_set(mysql))
|
||||
goto error;
|
||||
|
||||
if (mysql_init_charset(mysql))
|
||||
if (check_embedded_connection(mysql))
|
||||
goto error;
|
||||
|
||||
/* Send client information for access check */
|
||||
|
|
|
@ -133,6 +133,8 @@ static void mysql_close_free(MYSQL *mysql);
|
|||
static int wait_for_data(my_socket fd, uint timeout);
|
||||
#endif
|
||||
|
||||
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
A modified version of connect(). my_connect() allows you to specify
|
||||
|
@ -1424,7 +1426,7 @@ mysql_init(MYSQL *mysql)
|
|||
bzero((char*) (mysql),sizeof(*(mysql)));
|
||||
mysql->options.connect_timeout= CONNECT_TIMEOUT;
|
||||
mysql->last_used_con= mysql->next_slave= mysql->master = mysql;
|
||||
mysql->charset=default_charset_info;
|
||||
mysql->charset=default_client_charset_info;
|
||||
strmov(mysql->net.sqlstate, not_error_sqlstate);
|
||||
/*
|
||||
By default, we are a replication pivot. The caller must reset it
|
||||
|
@ -1537,6 +1539,50 @@ static MYSQL_METHODS client_methods=
|
|||
#endif
|
||||
};
|
||||
|
||||
C_MODE_START
|
||||
int mysql_init_character_set(MYSQL *mysql)
|
||||
{
|
||||
NET *net= &mysql->net;
|
||||
/* Set character set */
|
||||
if (!mysql->options.charset_name &&
|
||||
!(mysql->options.charset_name=
|
||||
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
|
||||
return 1;
|
||||
|
||||
{
|
||||
const char *save= charsets_dir;
|
||||
if (mysql->options.charset_dir)
|
||||
charsets_dir=mysql->options.charset_dir;
|
||||
mysql->charset=get_charset_by_csname(mysql->options.charset_name,
|
||||
MY_CS_PRIMARY, MYF(MY_WME));
|
||||
charsets_dir= save;
|
||||
}
|
||||
|
||||
if (!mysql->charset)
|
||||
{
|
||||
net->last_errno=CR_CANT_READ_CHARSET;
|
||||
strmov(net->sqlstate, unknown_sqlstate);
|
||||
if (mysql->options.charset_dir)
|
||||
my_snprintf(net->last_error, sizeof(net->last_error)-1,
|
||||
ER(net->last_errno),
|
||||
mysql->options.charset_name,
|
||||
mysql->options.charset_dir);
|
||||
else
|
||||
{
|
||||
char cs_dir_name[FN_REFLEN];
|
||||
get_charsets_dir(cs_dir_name);
|
||||
my_snprintf(net->last_error, sizeof(net->last_error)-1,
|
||||
ER(net->last_errno),
|
||||
mysql->options.charset_name,
|
||||
cs_dir_name);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
C_MODE_END
|
||||
|
||||
|
||||
MYSQL * STDCALL
|
||||
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
|
@ -1875,42 +1921,8 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||
goto error;
|
||||
}
|
||||
|
||||
/* Set character set */
|
||||
if (!mysql->options.charset_name &&
|
||||
!(mysql->options.charset_name=
|
||||
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
|
||||
if (mysql_init_character_set(mysql))
|
||||
goto error;
|
||||
|
||||
{
|
||||
const char *save= charsets_dir;
|
||||
if (mysql->options.charset_dir)
|
||||
charsets_dir=mysql->options.charset_dir;
|
||||
mysql->charset=get_charset_by_csname(mysql->options.charset_name,
|
||||
MY_CS_PRIMARY, MYF(MY_WME));
|
||||
charsets_dir= save;
|
||||
}
|
||||
|
||||
if (!mysql->charset)
|
||||
{
|
||||
net->last_errno=CR_CANT_READ_CHARSET;
|
||||
strmov(net->sqlstate, unknown_sqlstate);
|
||||
if (mysql->options.charset_dir)
|
||||
my_snprintf(net->last_error, sizeof(net->last_error)-1,
|
||||
ER(net->last_errno),
|
||||
mysql->options.charset_name,
|
||||
mysql->options.charset_dir);
|
||||
else
|
||||
{
|
||||
char cs_dir_name[FN_REFLEN];
|
||||
get_charsets_dir(cs_dir_name);
|
||||
my_snprintf(net->last_error, sizeof(net->last_error)-1,
|
||||
ER(net->last_errno),
|
||||
mysql->options.charset_name,
|
||||
cs_dir_name);
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
/* Save connection information */
|
||||
if (!my_multi_malloc(MYF(0),
|
||||
|
|
|
@ -667,6 +667,37 @@ static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
|
|||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
}
|
||||
|
||||
void thd_init_client_charset(THD *thd, uint cs_number)
|
||||
{
|
||||
/*
|
||||
Use server character set and collation if
|
||||
- opt_character_set_client_handshake is not set
|
||||
- client has not specified a character set
|
||||
- client character set is the same as the servers
|
||||
- client character set doesn't exists in server
|
||||
*/
|
||||
if (!opt_character_set_client_handshake ||
|
||||
!(thd->variables.character_set_client= get_charset(cs_number, MYF(0))) ||
|
||||
!my_strcasecmp(&my_charset_latin1,
|
||||
global_system_variables.character_set_client->name,
|
||||
thd->variables.character_set_client->name))
|
||||
{
|
||||
thd->variables.character_set_client=
|
||||
global_system_variables.character_set_client;
|
||||
thd->variables.collation_connection=
|
||||
global_system_variables.collation_connection;
|
||||
thd->variables.character_set_results=
|
||||
global_system_variables.character_set_results;
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->variables.character_set_results=
|
||||
thd->variables.collation_connection=
|
||||
thd->variables.character_set_client;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Perform handshake, authorize client and update thd ACL variables.
|
||||
SYNOPSIS
|
||||
|
@ -809,33 +840,7 @@ static int check_connection(THD *thd)
|
|||
thd->client_capabilities|= ((ulong) uint2korr(net->read_pos+2)) << 16;
|
||||
thd->max_client_packet_length= uint4korr(net->read_pos+4);
|
||||
DBUG_PRINT("info", ("client_character_set: %d", (uint) net->read_pos[8]));
|
||||
/*
|
||||
Use server character set and collation if
|
||||
- opt_character_set_client_handshake is not set
|
||||
- client has not specified a character set
|
||||
- client character set is the same as the servers
|
||||
- client character set doesn't exists in server
|
||||
*/
|
||||
if (!opt_character_set_client_handshake ||
|
||||
!(thd->variables.character_set_client=
|
||||
get_charset((uint) net->read_pos[8], MYF(0))) ||
|
||||
!my_strcasecmp(&my_charset_latin1,
|
||||
global_system_variables.character_set_client->name,
|
||||
thd->variables.character_set_client->name))
|
||||
{
|
||||
thd->variables.character_set_client=
|
||||
global_system_variables.character_set_client;
|
||||
thd->variables.collation_connection=
|
||||
global_system_variables.collation_connection;
|
||||
thd->variables.character_set_results=
|
||||
global_system_variables.character_set_results;
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->variables.character_set_results=
|
||||
thd->variables.collation_connection=
|
||||
thd->variables.character_set_client;
|
||||
}
|
||||
thd_init_client_charset(thd, (uint) net->read_pos[8]);
|
||||
thd->update_charset();
|
||||
end= (char*) net->read_pos+32;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue