summaryrefslogtreecommitdiff
path: root/sql/item_timefunc.cc
diff options
context:
space:
mode:
authorunknown <bar@mysql.com/bar.intranet.mysql.r18.ru>2006-11-08 15:37:54 +0400
committerunknown <bar@mysql.com/bar.intranet.mysql.r18.ru>2006-11-08 15:37:54 +0400
commitd301b4a0a52db2d2b66a2bd9feb6f84de163d36b (patch)
tree40ea85ba7514f23191a8a9dc8a060e24fb5ecb35 /sql/item_timefunc.cc
parentb227a3d3487802249408bb3edbc40d28e571b417 (diff)
downloadmariadb-git-d301b4a0a52db2d2b66a2bd9feb6f84de163d36b.tar.gz
Bug#22646 LC_TIME_NAMES: Assignment to non-UTF8 target fails
Problem: After introducing of LC_TIME_NAMES variable, the function date_format() can return international non-ascii characters in month and weekday names. Thus, it cannot return a binary string anymore, because inserting a result of date_format() into a column with non-utf8 character set produces garbage. Fix: date_format() now returns a character string, using "collation_connection" to detect character set and collation for the returned value. This allows to insert results of date_format() properly into columns with various character sets. mysql-test/r/ctype_utf8.result: Adding test case. Fixing old result. mysql-test/t/ctype_utf8.test: Adding test case. sql/item_timefunc.cc: DATE_FORMAT() now returns a character string instead of binary string: - make_date_time() now converts localte data from UTF8 to the character set of "str" argument, instead of copying as is. - fix_dec_and_length() now uses "collation_connection" instead of "binary" for the result, it also now multiplies to mbmaxlen when calculating max_length
Diffstat (limited to 'sql/item_timefunc.cc')
-rw-r--r--sql/item_timefunc.cc83
1 files changed, 36 insertions, 47 deletions
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index c1bca7afc60..8334c8ea3fa 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -595,16 +595,10 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
uint weekday;
ulong length;
const char *ptr, *end;
- MY_LOCALE *locale;
THD *thd= current_thd;
- char buf[128];
- String tmp(buf, sizeof(buf), thd->variables.character_set_results);
- uint errors= 0;
+ MY_LOCALE *locale= thd->variables.lc_time_names;
- tmp.length(0);
str->length(0);
- str->set_charset(&my_charset_bin);
- locale = thd->variables.lc_time_names;
if (l_time->neg)
str->append("-", 1);
@@ -618,41 +612,37 @@ bool make_date_time(DATE_TIME_FORMAT *format, TIME *l_time,
{
switch (*++ptr) {
case 'M':
- if (!l_time->month)
- return 1;
- tmp.copy(locale->month_names->type_names[l_time->month-1],
- strlen(locale->month_names->type_names[l_time->month-1]),
- system_charset_info, tmp.charset(), &errors);
- str->append(tmp.ptr(), tmp.length());
- break;
+ if (!l_time->month)
+ return 1;
+ str->append(locale->month_names->type_names[l_time->month-1],
+ strlen(locale->month_names->type_names[l_time->month-1]),
+ system_charset_info);
+ break;
case 'b':
- if (!l_time->month)
- return 1;
- tmp.copy(locale->ab_month_names->type_names[l_time->month-1],
- strlen(locale->ab_month_names->type_names[l_time->month-1]),
- system_charset_info, tmp.charset(), &errors);
- str->append(tmp.ptr(), tmp.length());
- break;
+ if (!l_time->month)
+ return 1;
+ str->append(locale->ab_month_names->type_names[l_time->month-1],
+ strlen(locale->ab_month_names->type_names[l_time->month-1]),
+ system_charset_info);
+ break;
case 'W':
- if (type == MYSQL_TIMESTAMP_TIME)
- return 1;
- weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
- l_time->day),0);
- tmp.copy(locale->day_names->type_names[weekday],
- strlen(locale->day_names->type_names[weekday]),
- system_charset_info, tmp.charset(), &errors);
- str->append(tmp.ptr(), tmp.length());
- break;
+ if (type == MYSQL_TIMESTAMP_TIME)
+ return 1;
+ weekday= calc_weekday(calc_daynr(l_time->year,l_time->month,
+ l_time->day),0);
+ str->append(locale->day_names->type_names[weekday],
+ strlen(locale->day_names->type_names[weekday]),
+ system_charset_info);
+ break;
case 'a':
- if (type == MYSQL_TIMESTAMP_TIME)
- return 1;
- weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
- l_time->day),0);
- tmp.copy(locale->ab_day_names->type_names[weekday],
- strlen(locale->ab_day_names->type_names[weekday]),
- system_charset_info, tmp.charset(), &errors);
- str->append(tmp.ptr(), tmp.length());
- break;
+ if (type == MYSQL_TIMESTAMP_TIME)
+ return 1;
+ weekday=calc_weekday(calc_daynr(l_time->year,l_time->month,
+ l_time->day),0);
+ str->append(locale->ab_day_names->type_names[weekday],
+ strlen(locale->ab_day_names->type_names[weekday]),
+ system_charset_info);
+ break;
case 'D':
if (type == MYSQL_TIMESTAMP_TIME)
return 1;
@@ -1638,8 +1628,9 @@ longlong Item_func_sec_to_time::val_int()
void Item_func_date_format::fix_length_and_dec()
{
+ THD* thd= current_thd;
decimals=0;
- collation.set(&my_charset_bin);
+ collation.set(thd->variables.collation_connection);
if (args[1]->type() == STRING_ITEM)
{ // Optimize the normal case
fixed_length=1;
@@ -1653,17 +1644,14 @@ void Item_func_date_format::fix_length_and_dec()
args[1]->collation.set(
get_charset_by_csname(args[1]->collation.collation->csname,
MY_CS_BINSORT,MYF(0)), DERIVATION_COERCIBLE);
- /*
- The result is a binary string (no reason to use collation->mbmaxlen
- This is becasue make_date_time() only returns binary strings
- */
- max_length= format_length(((Item_string*) args[1])->const_string());
+ max_length= format_length(((Item_string*) args[1])->const_string()) *
+ collation.collation->mbmaxlen;
}
else
{
fixed_length=0;
- /* The result is a binary string (no reason to use collation->mbmaxlen */
- max_length=min(args[1]->max_length,MAX_BLOB_WIDTH) * 10;
+ max_length= min(args[1]->max_length,MAX_BLOB_WIDTH) * 10 *
+ collation.collation->mbmaxlen;
set_if_smaller(max_length,MAX_BLOB_WIDTH);
}
maybe_null=1; // If wrong date
@@ -1783,6 +1771,7 @@ String *Item_func_date_format::val_str(String *str)
date_time_format.format.length= format->length();
/* Create the result string */
+ str->set_charset(collation.collation);
if (!make_date_time(&date_time_format, &l_time,
is_time_format ? MYSQL_TIMESTAMP_TIME :
MYSQL_TIMESTAMP_DATE,