summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-10-08 09:57:35 +0400
committerAlexander Barkov <bar@mariadb.org>2016-10-08 09:57:35 +0400
commit8ea2e143f09bd0602ffd9695a78c076d483dd65a (patch)
tree585821a4dbe502ad90ec51fe7cf3c4dcc4f95a5f
parent62d1cfe16c2aa7ab3c9925762b016c891672eefc (diff)
downloadmariadb-git-8ea2e143f09bd0602ffd9695a78c076d483dd65a.tar.gz
MDEV-10772 Introduce Item_param::CONVERSION_INFO
-rw-r--r--sql/item.cc57
-rw-r--r--sql/item.h60
2 files changed, 70 insertions, 47 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 8087aad2e7f..1b4935def56 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -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 */
/*
diff --git a/sql/item.h b/sql/item.h
index 5b8254837e8..a9381ba1517 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2727,6 +2727,47 @@ public:
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
@@ -2743,24 +2784,7 @@ public:
{
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;