diff options
author | Alexander Barkov <bar@mariadb.org> | 2016-10-08 09:57:35 +0400 |
---|---|---|
committer | Alexander Barkov <bar@mariadb.org> | 2016-10-08 09:57:35 +0400 |
commit | 8ea2e143f09bd0602ffd9695a78c076d483dd65a (patch) | |
tree | 585821a4dbe502ad90ec51fe7cf3c4dcc4f95a5f | |
parent | 62d1cfe16c2aa7ab3c9925762b016c891672eefc (diff) | |
download | mariadb-git-8ea2e143f09bd0602ffd9695a78c076d483dd65a.tar.gz |
MDEV-10772 Introduce Item_param::CONVERSION_INFO
-rw-r--r-- | sql/item.cc | 57 | ||||
-rw-r--r-- | sql/item.h | 60 |
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; |