Skip to content

Commit

Permalink
MDEV-10772 Introduce Item_param::CONVERSION_INFO
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Barkov committed Oct 8, 2016
1 parent 62d1cfe commit 8ea2e14
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 47 deletions.
57 changes: 28 additions & 29 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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 */

/*
Expand Down
60 changes: 42 additions & 18 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -2727,6 +2727,47 @@ class Item_param :public Item_basic_value,
DECIMAL_VALUE
} state;

struct CONVERSION_INFO
{
/*
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).
*/
CHARSET_INFO *character_set_client;
CHARSET_INFO *character_set_of_placeholder;
/*
This points at character set of connection if conversion
to it is required (i. e. if placeholder typecode is not BLOB).
Otherwise it's equal to character_set_client (to simplify
check in convert_str_value()).
*/
CHARSET_INFO *final_character_set_of_str_value;
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
Expand All @@ -2743,24 +2784,7 @@ class Item_param :public Item_basic_value,
{
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;
/*
This points at character set of connection if conversion
to it is required (i. e. if placeholder typecode is not BLOB).
Otherwise it's equal to character_set_client (to simplify
check in convert_str_value()).
*/
CHARSET_INFO *final_character_set_of_str_value;
} cs_info;
CONVERSION_INFO cs_info;
MYSQL_TIME time;
} value;

Expand Down

0 comments on commit 8ea2e14

Please sign in to comment.