Commit 8ea2e143 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10772 Introduce Item_param::CONVERSION_INFO

parent 62d1cfe1
......@@ -3412,6 +3412,32 @@ bool Item_param::set_longdata(const char *str, ulong length)
}
void Item_param::CONVERSION_INFO::set(THD *thd, CHARSET_INFO *fromcs)
{
CHARSET_INFO *tocs= thd->variables.collation_connection;
character_set_of_placeholder= fromcs;
character_set_client= thd->variables.character_set_client;
/*
Setup source and destination character sets so that they
are different only if conversion is necessary: this will
make later checks easier.
*/
uint32 dummy_offset;
final_character_set_of_str_value=
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
tocs : fromcs;
}
bool Item_param::CONVERSION_INFO::convert(THD *thd, String *str)
{
return thd->convert_string(str,
character_set_of_placeholder,
final_character_set_of_str_value);
}
/**
Set parameter value from user variable value.
......@@ -3451,20 +3477,7 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
break;
case STRING_RESULT:
{
CHARSET_INFO *fromcs= entry->charset();
CHARSET_INFO *tocs= thd->variables.collation_connection;
uint32 dummy_offset;
value.cs_info.character_set_of_placeholder= fromcs;
value.cs_info.character_set_client= thd->variables.character_set_client;
/*
Setup source and destination character sets so that they
are different only if conversion is necessary: this will
make later checks easier.
*/
value.cs_info.final_character_set_of_str_value=
String::needs_conversion(0, fromcs, tocs, &dummy_offset) ?
tocs : fromcs;
value.cs_info.set(thd, entry->charset());
/*
Exact value of max_length is not known unless data is converted to
charset of connection, so we have to set it later.
......@@ -3775,21 +3788,7 @@ bool Item_param::convert_str_value(THD *thd)
bool rc= FALSE;
if (state == STRING_VALUE || state == LONG_DATA_VALUE)
{
/*
Check is so simple because all charsets were set up properly
in setup_one_conversion_function, where typecode of
placeholder was also taken into account: the variables are different
here only if conversion is really necessary.
*/
if (value.cs_info.final_character_set_of_str_value !=
value.cs_info.character_set_of_placeholder)
{
rc= thd->convert_string(&str_value,
value.cs_info.character_set_of_placeholder,
value.cs_info.final_character_set_of_str_value);
}
else
str_value.set_charset(value.cs_info.final_character_set_of_str_value);
rc= value.cs_info.convert_if_needed(thd, &str_value);
/* Here str_value is guaranteed to be in final_character_set_of_str_value */
/*
......
......@@ -2727,30 +2727,14 @@ class Item_param :public Item_basic_value,
DECIMAL_VALUE
} state;
/*
A buffer for string and long data values. Historically all allocated
values returned from val_str() were treated as eligible to
modification. I. e. in some cases Item_func_concat can append it's
second argument to return value of the first one. Because of that we
can't return the original buffer holding string data from val_str(),
and have to have one buffer for data and another just pointing to
the data. This is the latter one and it's returned from val_str().
Can not be declared inside the union as it's not a POD type.
*/
String str_value_ptr;
my_decimal decimal_value;
union
struct CONVERSION_INFO
{
longlong integer;
double real;
/*
Character sets conversion info for string values.
Character sets of client and connection defined at bind time are used
for all conversions, even if one of them is later changed (i.e.
between subsequent calls to mysql_stmt_execute).
*/
struct CONVERSION_INFO
{
CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_of_placeholder;
/*
......@@ -2760,7 +2744,47 @@ class Item_param :public Item_basic_value,
check in convert_str_value()).
*/
CHARSET_INFO *final_character_set_of_str_value;
} cs_info;
private:
bool needs_conversion() const
{
return final_character_set_of_str_value !=
character_set_of_placeholder;
}
bool convert(THD *thd, String *str);
public:
void set(THD *thd, CHARSET_INFO *cs);
bool convert_if_needed(THD *thd, String *str)
{
/*
Check is so simple because all charsets were set up properly
in setup_one_conversion_function, where typecode of
placeholder was also taken into account: the variables are different
here only if conversion is really necessary.
*/
if (needs_conversion())
return convert(thd, str);
str->set_charset(final_character_set_of_str_value);
return false;
}
};
/*
A buffer for string and long data values. Historically all allocated
values returned from val_str() were treated as eligible to
modification. I. e. in some cases Item_func_concat can append it's
second argument to return value of the first one. Because of that we
can't return the original buffer holding string data from val_str(),
and have to have one buffer for data and another just pointing to
the data. This is the latter one and it's returned from val_str().
Can not be declared inside the union as it's not a POD type.
*/
String str_value_ptr;
my_decimal decimal_value;
union
{
longlong integer;
double real;
CONVERSION_INFO cs_info;
MYSQL_TIME time;
} value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment