summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mnogosearch.org>2013-11-08 14:18:16 +0400
committerAlexander Barkov <bar@mnogosearch.org>2013-11-08 14:18:16 +0400
commita33bb001445d2576f15437d9392bc70736ab419a (patch)
tree878fd523c8bcdac7fdfe7af8800bc28c92969fe1 /sql
parent5ce11d8b4ca2a57968656925a69ed8114d5374f6 (diff)
downloadmariadb-git-a33bb001445d2576f15437d9392bc70736ab419a.tar.gz
MDEV-4842 STR_TO_DATE does not work with UCS2/UTF16/UTF32
Diffstat (limited to 'sql')
-rw-r--r--sql/item.cc18
-rw-r--r--sql/item.h4
-rw-r--r--sql/item_timefunc.cc18
-rw-r--r--sql/item_timefunc.h6
4 files changed, 42 insertions, 4 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 803c9fee576..a415464a2f9 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -218,6 +218,24 @@ bool Item::val_bool()
}
+String *Item::val_str(String *str, String *converter, CHARSET_INFO *cs)
+{
+ String *res= val_str(str);
+ if (null_value)
+ return (String *) 0;
+
+ if (!cs)
+ return res;
+
+ uint errors;
+ if ((null_value= converter->copy(res->ptr(), res->length(),
+ collation.collation, cs, &errors)))
+ return (String *) 0;
+
+ return converter;
+}
+
+
String *Item::val_string_from_real(String *str)
{
double nr= val_real();
diff --git a/sql/item.h b/sql/item.h
index 4f03d588bbc..084e77e4d23 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -794,6 +794,10 @@ public:
*/
virtual String *val_str(String *str)=0;
/*
+ Returns the val_str() value converted to the given character set.
+ */
+ String *val_str(String *str, String *converter, CHARSET_INFO *to);
+ /*
Return decimal representation of item with fixed point.
SYNOPSIS
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 6c304946abc..cb60368aafd 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -2980,13 +2980,25 @@ get_date_time_result_type(const char *format, uint length)
void Item_func_str_to_date::fix_length_and_dec()
{
+ if (agg_arg_charsets(collation, args, 2, MY_COLL_ALLOW_CONV, 1))
+ return;
+ if (collation.collation->mbminlen > 1)
+ {
+#if MYSQL_VERSION_ID > 50500
+ internal_charset= &my_charset_utf8mb4_general_ci;
+#else
+ internal_charset= &my_charset_utf8_general_ci;
+#endif
+ }
+
cached_field_type= MYSQL_TYPE_DATETIME;
decimals= NOT_FIXED_DEC;
if ((const_item= args[1]->const_item()))
{
char format_buff[64];
String format_str(format_buff, sizeof(format_buff), &my_charset_bin);
- String *format= args[1]->val_str(&format_str);
+ String *format= args[1]->val_str(&format_str, &format_converter,
+ internal_charset);
decimals= 0;
if (!args[1]->null_value)
{
@@ -3024,8 +3036,8 @@ bool Item_func_str_to_date::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
String format_str(format_buff, sizeof(format_buff), &my_charset_bin),
*format;
- val= args[0]->val_str(&val_string);
- format= args[1]->val_str(&format_str);
+ val= args[0]->val_str(&val_string, &subject_converter, internal_charset);
+ format= args[1]->val_str(&format_str, &format_converter, internal_charset);
if (args[0]->null_value || args[1]->null_value)
goto null_date;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 20365d4f25d..bc048e1ff64 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -998,9 +998,13 @@ class Item_func_str_to_date :public Item_temporal_func
enum_field_types cached_field_type;
timestamp_type cached_timestamp_type;
bool const_item;
+ String subject_converter;
+ String format_converter;
+ CHARSET_INFO *internal_charset;
public:
Item_func_str_to_date(Item *a, Item *b)
- :Item_temporal_func(a, b), const_item(false)
+ :Item_temporal_func(a, b), const_item(false),
+ internal_charset(NULL)
{}
bool get_date(MYSQL_TIME *ltime, uint fuzzy_date);
const char *func_name() const { return "str_to_date"; }