#At file:///home/gluh/MySQL/mysql-5.0-bug-37575/
2714 Sergey Glukhov 2008-11-14
Bug#37575 UCASE fails on monthname
The MONTHNAME/DAYNAME functions
returns binary string, so the LOWER/UPPER functions
are not effective on the result of MONTHNAME/DAYNAME
call.
Character set of the MONTHNAME/DAYNAME function
result has been changed to connection character set.
modified:
mysql-test/r/func_time.result
mysql-test/t/func_time.test
sql/item_timefunc.cc
sql/item_timefunc.h
sql/mysql_priv.h
sql/mysqld.cc
per-file messages:
mysql-test/r/func_time.result
test result
mysql-test/t/func_time.test
test case
sql/item_timefunc.cc
Item_func_monthname::fix_length_and_dec and
Item_func_dayname::fix_length_and_dec methods have been
modified to use connection character set
sql/item_timefunc.h
Item_func_monthname::fix_length_and_dec and
Item_func_dayname::fix_length_and_dec methods have been
modified to use connection character set
sql/mysql_priv.h
MAX_MONTH_NAME_LEN and MAX_DAY_NAME_LEN constants has been defined
(see the test_lc_time_sz function for initial calculation).
sql/mysqld.cc
test_lc_time_sz function have been added.
The test_lc_time_sz function controls modifications
of the locale database in debugging mode.
=== modified file 'mysql-test/r/func_time.result'
--- a/mysql-test/r/func_time.result 2008-02-25 10:25:57 +0000
+++ b/mysql-test/r/func_time.result 2008-11-14 11:46:00 +0000
@@ -1308,4 +1308,22 @@ SELECT '2008-02-18' + INTERVAL 1 FRAC_SE
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'FRAC_SECOND' at line 1
+SELECT CHARSET(DAYNAME(19700101));
+CHARSET(DAYNAME(19700101))
+latin1
+SELECT CHARSET(MONTHNAME(19700101));
+CHARSET(MONTHNAME(19700101))
+latin1
+SELECT LOWER(DAYNAME(19700101));
+LOWER(DAYNAME(19700101))
+thursday
+SELECT LOWER(MONTHNAME(19700101));
+LOWER(MONTHNAME(19700101))
+january
+SELECT UPPER(DAYNAME(19700101));
+UPPER(DAYNAME(19700101))
+THURSDAY
+SELECT UPPER(MONTHNAME(19700101));
+UPPER(MONTHNAME(19700101))
+JANUARY
End of 5.0 tests
=== modified file 'mysql-test/t/func_time.test'
--- a/mysql-test/t/func_time.test 2008-02-27 15:12:08 +0000
+++ b/mysql-test/t/func_time.test 2008-11-14 11:46:00 +0000
@@ -829,4 +829,15 @@ SELECT '2008-02-18' + INTERVAL 1 FRAC_SE
--error ER_PARSE_ERROR
SELECT '2008-02-18' - INTERVAL 1 FRAC_SECOND;
+#
+# Bug#37575: UCASE fails on monthname
+#
+
+SELECT CHARSET(DAYNAME(19700101));
+SELECT CHARSET(MONTHNAME(19700101));
+SELECT LOWER(DAYNAME(19700101));
+SELECT LOWER(MONTHNAME(19700101));
+SELECT UPPER(DAYNAME(19700101));
+SELECT UPPER(MONTHNAME(19700101));
+
--echo End of 5.0 tests
=== modified file 'sql/item_timefunc.cc'
--- a/sql/item_timefunc.cc 2008-01-23 18:48:29 +0000
+++ b/sql/item_timefunc.cc 2008-11-14 11:46:00 +0000
@@ -1036,6 +1036,20 @@ longlong Item_func_month::val_int()
}
+void Item_func_monthname::fix_length_and_dec()
+{
+ THD* thd= current_thd;
+ CHARSET_INFO *cs= thd->variables.collation_connection;
+ uint32 repertoire= cs->state;
+ if (!thd->variables.lc_time_names->is_ascii)
+ repertoire|= MY_REPERTOIRE_EXTENDED;
+ collation.set(cs, DERIVATION_EXPLICIT, repertoire);
+ decimals=0;
+ max_length= MAX_MONTH_NAME_LEN * collation.collation->mbmaxlen;
+ maybe_null=1;
+}
+
+
String* Item_func_monthname::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
@@ -1050,7 +1064,8 @@ String* Item_func_monthname::val_str(Str
}
null_value=0;
month_name= thd->variables.lc_time_names->month_names->type_names[month-1];
- str->set(month_name, strlen(month_name), system_charset_info);
+ str->length(0);
+ str->append(month_name, strlen(month_name), collation.collation);
return str;
}
@@ -1170,6 +1185,20 @@ longlong Item_func_weekday::val_int()
}
+void Item_func_dayname::fix_length_and_dec()
+{
+ THD* thd= current_thd;
+ CHARSET_INFO *cs= thd->variables.collation_connection;
+ uint32 repertoire= cs->state;
+ if (!thd->variables.lc_time_names->is_ascii)
+ repertoire|= MY_REPERTOIRE_EXTENDED;
+ collation.set(cs, DERIVATION_EXPLICIT, repertoire);
+ decimals=0;
+ max_length= MAX_DAY_NAME_LEN * collation.collation->mbmaxlen;
+ maybe_null=1;
+}
+
+
String* Item_func_dayname::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
@@ -1181,7 +1210,8 @@ String* Item_func_dayname::val_str(Strin
return (String*) 0;
day_name= thd->variables.lc_time_names->day_names->type_names[weekday];
- str->set(day_name, strlen(day_name), system_charset_info);
+ str->length(0);
+ str->append(day_name, strlen(day_name), collation.collation);
return str;
}
=== modified file 'sql/item_timefunc.h'
--- a/sql/item_timefunc.h 2008-01-07 16:55:05 +0000
+++ b/sql/item_timefunc.h 2008-11-14 11:46:00 +0000
@@ -113,13 +113,7 @@ public:
const char *func_name() const { return "monthname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=10*my_charset_bin.mbmaxlen;
- maybe_null=1;
- }
+ void fix_length_and_dec();
};
@@ -277,13 +271,7 @@ class Item_func_dayname :public Item_fun
const char *func_name() const { return "dayname"; }
String *val_str(String *str);
enum Item_result result_type () const { return STRING_RESULT; }
- void fix_length_and_dec()
- {
- collation.set(&my_charset_bin);
- decimals=0;
- max_length=9*MY_CHARSET_BIN_MB_MAXLEN;
- maybe_null=1;
- }
+ void fix_length_and_dec();
};
=== modified file 'sql/mysql_priv.h'
--- a/sql/mysql_priv.h 2008-10-02 11:57:52 +0000
+++ b/sql/mysql_priv.h 2008-11-14 11:46:00 +0000
@@ -122,6 +122,16 @@ enum Derivation
};
+/*
+ Maximal number of UTF-8 characters in month/day name
+ over the locale database (see the sql_locale.cc file).
+ Both values should be checked/updated after every
+ modification of that database. The test_lc_time_sz
+ function (see mysqld.cc) controls such modifications.
+*/
+#define MAX_MONTH_NAME_LEN 18
+#define MAX_DAY_NAME_LEN 14
+
typedef struct my_locale_st
{
uint number;
=== modified file 'sql/mysqld.cc'
--- a/sql/mysqld.cc 2008-10-09 07:26:42 +0000
+++ b/sql/mysqld.cc 2008-11-14 11:46:00 +0000
@@ -3614,6 +3614,32 @@ void decrement_handler_count()
#endif /* defined(__NT__) || defined(HAVE_SMEM) */
+/*
+ Debugging helper function to keep the locale database
+ (see sql_locale.cc) and the MAX_MONTH_NAME_LEN and
+ MAX_DAY_NAME_LEN variable values in consistent state.
+*/
+static void test_lc_time_sz()
+{
+ uint max_month_len= 0;
+ uint max_day_len = 0;
+ for (MY_LOCALE **loc= my_locales; *loc; loc++)
+ {
+ for (const char **month= (*loc)->month_names->type_names; *month; month++)
+ set_if_bigger(max_month_len,
+ my_numchars_mb(&my_charset_utf8_general_ci,
+ *month, *month + strlen(*month)));
+ for (const char **day= (*loc)->day_names->type_names; *day; day++)
+ set_if_bigger(max_day_len,
+ my_numchars_mb(&my_charset_utf8_general_ci,
+ *day, *day + strlen(*day)));
+ }
+ DBUG_ASSERT(max_month_len <= MAX_MONTH_NAME_LEN);
+ DBUG_ASSERT(max_day_len <= MAX_DAY_NAME_LEN);
+ return;
+}
+
+
#ifndef EMBEDDED_LIBRARY
#ifdef __WIN__
int win_main(int argc, char **argv)
@@ -3710,6 +3736,8 @@ int main(int argc, char **argv)
openlog(libwrapName, LOG_PID, LOG_AUTH);
#endif
+ test_lc_time_sz();
+
/*
We have enough space for fiddling with the argv, continue
*/
| Thread |
|---|
| • bzr commit into mysql-5.0-bugteam branch (Sergey.Glukhov:2714)Bug#37575 | Sergey Glukhov | 14 Nov |